OmniAICreator/Qiita-1.07M huggingface dataset:
ETL とは

## 勉強前イメージ

DBってイメージ

## 調査

### ETL とは

Extract(抽出),Transform(変換),Load(書き出し)の頭文字を取ったもので
膨大なデータを分析しやすい形にする処理、それを支援するソフトウェアがETLになります。
主にBIツールのために作成されるデータウェアハウス(DWH)を構築するときに
発生するプロセスとして用いられています。

- 抽出

基幹システムやデータベースからデータの抽出を行います。

- 変換

DWHに書き出しやすいようにデータの変換を行います。

- 書き出し

変換のプロセスを踏んだデータをDWHに書き出します。

### ETLの特徴

- 大量のデータの変換・加工が得意
- 高速での処理が可能
- メタデータの管理が可能

### ETLのメリット

- 開発工数の削減

ツールはデータの統合に必要な部品を提供しており、
組み合わせてデータ統合のプログラムができます。
組わせるのも直感的に操作できます。

- データ品質の向上

データのフォーマットが点在していても適切なデータ形式に変換されます。
またデータの重複や誤りを自動修正するので、初心者でも室の高いデータ統合ができます。

## 勉強後イメージ

聞いたことあったけど実際よく知らなかった....
DBじゃなくてDBのデータを加工したりすることなのね。

## 参考

- [ETLとは？3つの機能、特徴を解説 - BIやDWHとの違い](https://boxil.jp/mag/a2415/?utm_source=google&utm_medium=cpc&utm_campaign=dsa-all&gclid=CjwKCAjwzaSLBhBJEiwAJSRokpAQLuFzpJvo-5w1fnnQLbW-hNE4HdqFMHGJDbb72ZlgYkdgqQ6a-hoCxsoQAvD_BwE)
- [ETLとは？３つの機能・必要性を知ってデータを有効活用！](https://it-trend.jp/etl/article/function)
UbuntuのTerminalのカラーをicebergにする

## 概要

Terminalアプリの設定からカスタムスキーマ（Colors＞Palette＞Built-in schemes＞Custom）を設定していきます。

![Screenshot from 2021-10-15 22-05-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148042/c0ed1cb3-3f7a-ca71-ce4c-04608885eb5f.png)

## 手順

画像の通り8x2=16個のカラーを選んでいくのですが、__下記のページ__を参考にします。
（cocopon/iceberg.vimのリポジトリにissueが上がっていたようで、そのプルリクの内容を参考にしました）

https://github.com/cocopon/iceberg.vim/commit/5f3c2b24b638c7d5e37ec801342f6e19cb589671#diff-79c4240f9bb79f5be8c8ca9f7833082aa0e23ba72472e4cd2fb56e48182fad67

こんな感じで0〜15まであるので、１つずつ設定していきます。

| Palette | code |
|:-:|:-:|
| Color 0 | #161821 |
| Color 1 | #e27878 |
| Color 2 | #b4be82 |
| Color 3 | #e2a478 |
| Color 4 | #84a0c6 |
| Color 5 | #a093c7 |
| Color 6 | #89b8c2 |
| Color 7 | #c6c8d1 |
| Color 8 | #6b7089|
| Color 9 | #e98989 |
| Color 10 | #c0ca8e |
| Color 11 | #e9b189 |
| Color 12 | #91acd1 |
| Color 13 | #ada0d3 |
| Color 14 | #95c4ce |
| Color 15 | #d2d4de |

![Screenshot from 2021-10-15 22-28-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148042/cc188fdb-dced-7c75-a96b-27f42a4768a2.png)

## 完成形

最終的にこんな感じのicebergっぽい感じになりました。

![Screenshot from 2021-10-15 22-37-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148042/5abbc878-55f5-f8af-89fb-7a33c3b871f8.png)
Googleの脆弱性？メタマスクの設定・利用時の注意点

こんにちは、nicoin39と申します:feet:

仮想通貨のウォレットとして使われている**メタマスクの実装セキュリティ**についての備忘録です。

いきなりソースコードの話ではなく恐縮ですが、大手取引所の記事にも注意点として記載されていないため、「プログラムサービスレビュー」としてこちらに記載します。

#メタマスクの拡張機能の設定について

実装後、すぐに確認して欲しいのは、**「拡張機能の設定」**についてです。

![めた.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2174529/206feb9f-8ccb-d46d-712f-e5e532a50734.png)

①　右上のパズルのような形の部分をクリックします。

②　MetaMaskの右側にある点3つの部分をクリックします。

③　「サイトデータの読み取りと変更を行います」が出てくるので、そこにカーソルを合わせます。

④　初期設定では自動的に「すべてのサイト」が選択されているため、「拡張機能をクリックしたとき」に変更しておきましょう。

#メタマスクは危険なのか？

メタマスク側は「個人情報を取ったりはしないよ～」と述べています。

それでも、何もしていない時にすべてのサイトのデータを見られているかもしれないと思うと不安ですよね。

サービスそのものが乗っ取られたら･･･。万が一にも備えたいものです。

もしかしたら、メタマスク本体ではなく、Google側の問題なのではないかとも考えられます。

#許可も確認もなく自動で設定されるのが嫌だなという話

無料でインストールと利用ができるのはありがたいですが、仮にセキュリティ的に問題がなかったとしても、**拡張機能を自動的に設定されるのは嫌**だなと。

「調べたら分かる」「利用規約に書いてあります」ではなく、「拡張機能についてはどのように選択しますか？」と、メタマスクなどのサービス側もしくはGoogle側から事前に聞いてくれたら嬉しいなと。

そのようなことを思い書いてみました。
【初心者向け】 企業で活躍できるエンジニアになるためのロードマップ①　Web編

##目的
みなさんエンジニアを目指して日々勉強していると思います！
勉強してるけど、これで本当に稼げるエンジニアになれるの？？と不安な人がたくさんいるでしょう！
今回は未経験の人、プログラミング初心者　が
**「企業で活躍できるエンジニア」** **「どこでも成長できるエンジニア」**
になるためのロードマップを作成しましたので是非みていってください。

まずは、Webアプリケーションエンジニアを目指しましょう！

こちらに移行しました！

https://sg-report.com/loadmap1/
FlutterのList<Map<String,dynamic>>をintやDateTimeでsortする

##数字が大きい順
```dart
void sort() {
  final List<Map<String,dynamic>> list = [
    {'score': 1},
    {'score': 2},
    {'score': 3}
  ];
  list.sort((a,b) => b['score'].compareTo(a['score']));
  print(list);
}
  
```
###結果
```dart
[{score: 3}, {score: 2}, {score: 1}]
```

##数字が小さい順
```dart
void sort(){
  final List<Map<String,dynamic>> list = [
    {'score': 1},
    {'score': 2},
    {'score': 3}
  ];
  list.sort((a,b) => a['score'].compareTo(b['score']));
  print(list);
}

```
###結果
```dart
[{score: 1}, {score: 2}, {score: 3}]
```

##新しい順
```dart
void sort(){
  final firstDay = DateTime(2021,10,10);
  final nextDay = DateTime(2021,10,11);
  final nextNextDay = DateTime(2021,10,12);
  final List<Map<String,dynamic>> timeStamps = [
    {'createdAt': firstDay},
    {'createdAt': nextDay},
    {'createdAt': nextNextDay}
  ];
  timeStamps.sort((a,b) => b['createdAt'].compareTo(a['createdAt']));
  print(timeStamps);
}
```
###結果
```dart
[{createdAt: 2021-10-12 00:00:00.000}, {createdAt: 2021-10-11 00:00:00.000}, {createdAt: 2021-10-10 00:00:00.000}]
```

##古い順
```dart
void sort(){
  final firstDay = DateTime(2021,10,10);
  final nextDay = DateTime(2021,10,11);
  final nextNextDay = DateTime(2021,10,12);
  final List<Map<String,dynamic>> timeStamps = [
    {'createdAt': firstDay},
    {'createdAt': nextDay},
    {'createdAt': nextNextDay}
  ];
  timeStamps.sort((a,b) => a['createdAt'].compareTo(b['createdAt']));
  print(timeStamps);
}
```

###結果
```dart
[{createdAt: 2021-10-10 00:00:00.000}, {createdAt: 2021-10-11 00:00:00.000}, {createdAt: 2021-10-12 00:00:00.000}]
```
バリデーションエラーを日本語にする

#目的
ここでは、バリデーションエラーを日本語にする方法の大枠を記述します。（モデル名以外）
ちなみに、モデル名やdeviseのエラー文を日本語設定したい場合は、参考文献からのリンク記事を参考にしてください！



##開発環境
rails6.0.0
mysql

##参考文献
こちらを参考にさせていただいております！
本当にわかりやすくてありがとうございました！！
[■Railsのバリデーションエラーのメッセージの日本語化](https://qiita.com/Ushinji/items/242bfba84df7a5a67d5b)
→モデル名まで日本語にしたい方は、こちらをご参考ください！

[■translation missing: ja.activerecord〜のエラー対応](https://qiita.com/nkekisasa222/items/0c566ced53f7ee47d67d)
[■https://github.com/tigrish/devise-i18n/blob/master/rails/locales/ja.yml](https://github.com/tigrish/devise-i18n/blob/master/rails/locales/ja.yml
)
→deviseのバリデーションエラーの日本語化は、上記２つをご参考ください！

##エラーメッセージを日本語にする
####① gem 'rails-i18n'

gemを使います！
Gemfileに上記記述を行い、bundle installする。

####② config.i18n.default_locale = :ja

config/application.rbにて上記記述すれば完了！
サーバー再起動すれば、エラーメッセージが日本語になります。

##注意点
日本語になるため、テストコードもそれに応じて日本語に変更をしましょう！
PHP,Laravelでメモアプリを作った際の忘却録

##Dockerのインストールとdockerコマンドの使用
私が使用しているMacにdockerをインストールしてdockerコマンドを使えるようにするらしい

この前のrailsを使ったLINE-botもそうだが
何かの外部からのコマンドを使えるようにするには
外部からインストールするというのが方法のようだ

###Dockerとは
Dockerとは現在使用しているパソコンにnginx(最も高い稼働率を誇るサイトのうち約65%以上で広範囲に支持されている高信頼のWebサーバシステム)やMySQL(オープンソースのリレーショナルデータベース管理システム)などの開発に必要とされるソフトウェアを簡単にインストールして動かせる技術のこと。

###確認
そんなDockerをインストールして実際にターミナルでコマンド入力できるか確認

すると

```
> docker-compose -v
unknown shorthand flag: 'v' in -v
```

とでた

```
docker-compose --version
Docker Compose version v2.0.0-rc.3
```

このようにコマンド入力したらバージョンが出た。
よかった。

##PHPの環境構築の際のエラー
さて、今回はPHPを使用するのだが
Git Hubから環境構築用のファイルを取得し、
docker-composeコマンドを使って環境の立ち上げを行なった

```
docker-compose -f .docker_memo/docker-compose.yml up -d
```

このコマンドを使用することで環境構築を自動で行なってくれるらしい

```
Recreating php_simple_memo_mysql ... done
Recreating php_simple_memo_phpmyadmin ... done
Creating php_simple_memo_php          ... done
Creating php_simple_memo_nginx        ... done
```

無事完了した

これで、mysql, phpmyadmin, php, nginxが起動している状態になった。

また

```
docker ps
```
こちらのコマンドで起動状況の確認ができた


##実行されているアプリケーションの環境の停止と起動
###停止

```
docker-compose -f .docker_memo/docker-compose.yml down
```

###起動

```
docker-compose -f .docker_memo/docker-compose.yml up -d
```

##Laravel
createメソッド→モデルに**$fillable**または**$guarded**変数を作成して、設定をしないといけません。
$guarded→更新できないカラムを列挙した一覧を設定

$fillable→更新できるカラムを列挙した一覧を設定

##dockerコンテナに入ってlaravelのマイグレーションを行なった際に発生したエラー
dockerコンテナに入って

```
php artisan migrate
```

を実行したところ

```
Nothing to migrate
```
というエラーが発生した
どうやらmigrateするものはないとのこと

```
php artisan migrate:fresh
```
で実行したところ

```
Dropped all tables successfully.
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (78.65ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (51.53ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (61.13ms)
Migrating: 2021_10_09_122745_create_memos_table
Migrated:  2021_10_09_122745_create_memos_table (30.86ms)
```

となって成功した。

この:freshを行うことで全てのテーブルをドロップしてから再びマイグレーションできるらしい

##PHPとLaravelのファイルやディレクトリの作成の違い
PHP→mkdirやcd,vimを使用してファイルやディレクトリの作成を行う
Laravel→dockerコンテナに入ってコマンドを実行して作成


##PHPとLaravelの両方で同じ機能のメモアプリを作った感想
・LaravelではMVCのアーキテクチャにより、どこでどの処理が行われているのかの判断がしやすく、エラー部分に気づきやすかった。
・大規模開発になればなるほど管理の面からLaravelの恩恵を受けやすいと感じた。
・小規模であったり単体の実装であればPHPで行うのが良いのでは？と感じた
vs codeのターミナルでgit pushしてError: connect ECONNREFUSED...と怒られたとき

## git pushしたらエラー
```
$ git push
...
Missing or invalid credentials.
Error: connect ECONNREFUSED /run/user/1546/vscode-git-f7c0b94a0e.sock
    at PipeConnectWrap.afterConnect [as oncomplete] (net.js:1146:16) {
  errno: -111,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '/run/user/1546/vscode-git-f7c0b94a0e.sock'
}
fatal: Authentication failed for 'https://*****'
```

と怒られた。
素直にvscodeのソース管理から操作すればいいのだろうけど、60K+とか書いてあって触りたくない。

## 解決
vs codeがGIT_ASKPASSを設定しているのが悪い。

```bash
$ export GIT_ASKPASS=
```

をすれば素直にターミナルでユーザ・パスワードを聞かれるようになる。
LANとWANについて

# はじめに
本記事では、`LAN`と`WAN`について記述します。

# ネットワーク構成
さまざまな職場では、`LAN`と`WAN`で構成されています。

## LAN
`Local Area Network`の略。
建物内、各フロア内などで設置されている比較的狭い範囲のネットワークです。
(ex)
東京本社のビルはLANが設置されています。

## WAN
`Wide Area Network`の略。
通信事業者の回線を利用して、物理的に離れたところを繋ぐネットワークのことです。

(ex)
東京本社や名古屋支店、大阪支店の間にはWANが設置されています。

# ネットワークの構成している要素
まず、ネットワークの構成している装置を紹介します。

```
[有線の場合]
ルーター
↓
ハブ
↓
各パソコンたち
```

```
[無線の場合]
ルーター
↓
各パソコンたち
```

となります。

## ハブ
LANケーブルをまとめる`集線装置`で、LANの端末を`相互接続`する機器です。
ということは、接続口には、複数のLANポートがあります。

[ハブのイメージです](https://www.biccamera.com/bc/i/topics/osusume_switching_hub/index.jsp)

### リピータハブ
通信ネットワークの集線装置（ハブ）の種類の一つで、
`すべての信号`を`すべての端末に送る`機器です。
構造や動作が`最も単純なハブ`で、信号の増幅や波形の調整程度の物理的な処理しか行えません。

最近では、`L2スイッチ`の影響でほとんど、見かけません。

[リピータハブの参考サイト](https://www.infraexpert.com/study/ethernet6.html)

### スイッチングハブ
データに含まれる`MACアドレス`（ネットワーク機器に割り当てられた住所）を解析して、
データをどこの宛先の端末に送るか判断します。

同じ機能として`L2スイッチ`があります。

[スイッチングハブの参考サイト](https://wa3.i-3-i.info/word1956.html)

## ルータ
異なるネットワークを互いに接続し、
適している経路を選んで、`データの中継`を行ってくれる装置です。

受信したデータの`IPアドレス`を解析して、
適切なネットワークに転送します。

https://qiita.com/mkato1013/items/91a1e742c6ed40aaff4f#ip%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9

同じ機能として`L3スイッチ`という装置があります。

## ゲートウェイ
`直接通信ができない`ネットワークや`規格の違う`ネットワークを`中継`する機器のことです。

(ex)
携帯のメールとパソコンのメールとのやりとりができるように、ゲートウェイが働いています。

[ゲートウェイの参考サイト](https://amnimo.com/column/001/)

## LANケーブル
耳にしたことはあると思います。

ルータ、ハブ、コンピューターなどのケーブルのことです。

以上です。

# 終わりに
プログラミングの記事というよりかは、
ITパスポートに出てくる知識のアウトプットでした。

試験が近いので少々多くなっていますが、お付き合いください。

明日も頑張ります！
Flutter iOS ERROR ITMS-90208 Upload Failed

## エラー内容

```
ERROR ITMS-90208: "Invalid Bundle. The bundle Runner.app/Frameworks/App.framework does not support the minimum OS Version specified in the Info.plist."
```

## 対処できたFultterのバージョン
```
~$ flutter --version
Flutter 2.6.0-11.0.pre • channel dev • https://github.com/flutter/flutter.git
Framework • revision 4b330ddbed (4 weeks ago) • 2021-09-16 17:29:58 -0700
Engine • revision 5b81c6d615
Tools • Dart 2.15.0 (build 2.15.0-116.0.dev)
```
## 対処方法
普通にビルドした後にアーカイブ化したファイルの中の info.plistのMinimumOSVersionを修正する

### ①普通にビルド
```
flutter build ios --release
```
### アーカイブ化
Xcodeもしくはコマンドでアーカイブを作成する

### Flutter.framework/info.plistを修正
XcodeのOrganizerでアーカイブ化されたファイルを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167934/3ee665ff-4e58-b843-f45d-69b28ee22e8c.png)

```
~/Library/Developer/Xcode/Archives/日時/Runner 日時.xcarchive/Products/Applications/Runner.app/Frameworks/Flutter.framework/Info.plist
```
VSCODEなどで開く
```<key>MinimumOSVersion</key>
<string>9.0</string>
```
なぜか 8.0 になっているので 8.0 → 9.0 に修正


## 参考までに
関係あるかわからないが成功した時は
以下の値は初期状態から何もいじっていない9.0です。
iOS Deployment Target 9.0
Deployment Info iOS 9.0
AppFrameworkInfoのMinimumOSVersion 9.0


## おまけ（ここまでの過程）
stackoverflow、githubを見ながら、いろんな方法を試した。投稿日も古いのでFultterのバージョンで対処方法が異なるよう。AppleがFlutterを毛嫌いして弾いているのかと妄想もしてしまった。当方の環境と同じ方であればやってみる価値あるとおもいます。

以下は参考にしたサイト８割がた参考にはならなかった

https://github.com/flutter/flutter/issues/58200

https://stackoverflow.com/questions/60637731/uploading-flutter-app-to-appstore-gives-app-framework-does-not-support-the-minim/64367723#64367723
【CSS】textareaタグに入力した値を改行

#はじめに#
　formタグの中にtextareaタグを作成して文章を投稿したい時に、改行させて入力することもあります。そのままデータベースに保存→データを取得して表示すると、なんと改行が消えてしまっています。
　今回はこれを解消しようと思います。

#CSSを使った方法#
　改行は消えてしまっていますが、そこにはちゃんとHTMLエンティティという特殊な文字で改行の情報が保存されています。
　CSSを使って、改行させることができます。

```style.css
.comment {
    white-space: pre-wrap;
}
```
white-spaceは、CSSのプロパティで、要素内のホワイトスペースをどう扱うかを決めるプロパティです。
pre-wrapとすることで改行が反映されます！


ちょっとしたことですが、ブラウザへの表示は意外とハマりやすいので、備忘録として残しておきます。
DePay(現状まだ開発中) で Web3 で crypto 支払いしたいメモ

## 背景

EC ショップひらいて(e.g. vue storefront とか), ETH, USDC, JPYC とかで決済したい.

自前で web3 API(RPC)叩くのめんどそう...

ドル建て価格表示するとか, 支払いできる通貨をいろいろユーザーフレンドリーなことやろうとすると Infra などで処理しないと行けない部分が出てきます.

stripe みたいにぺろっと組み込めるのほしい.

なるべくソースコードとか公開されていて基本は無料で使えるのほしい

Depay が良さそうです. 

https://depay.fi/products/payments

オシャンティな UI がいいですね.

ただ, 無料で使えるかどうかは不明である. 現状開発中で, リリースは今年度中とある 

https://depay.fi/products/pro 

## Depay

ethereum と bsc(Binance Smart Chain)に対応しています.

Rinkerby など testnet はありません(ローカルで geth 建てるなどして,  cypress テストフレームワークでテストするしかないっぽい)

ソースコードゴニョゴニョ書き換えれば Rinkerby とか, Matic チェーンとか使えるかもしれませんが, 一部機能は depay サーバで処理しているため, ダメそうです.

API キーがいります. test 用のキーは document にあります. 

PRO 版は https://depay.fi/products/pro ですが, まだリリースされていません.

将来的には subscription(BNPL 的なのも?)などいろいろ機能つくっぽいようです.

とりあえずは今後に期待でしょうか.
SEO対策のススメ

#はじめに
今回は、知識編としてGoogleのアルゴリズムをまとめていきます。
結果として、検索結果を上位2位に入れ込むことができました。（被リンクは0件です。）

#Googleアルゴリズム
毎日6~8個のアルゴリズムが更新されていると言われています。
なので毎日検索順位が変動します。

前提知識としてアルゴリズムは公表されません。
しかし公表してくれているコロナの影響もあってか公表した情報があるのでそちらを共有していきます。

#Page Experience
①ユーザーが好むページが評価され、嫌うページの評価が下げられる。
(追従してくるポップアップ広告等)

②文が改行されていないや文に誤字があるのは修正案件。
（その他「ページの表示速度」「見にくいデザイン」等）

③ページレベルで適用されているアルゴリズムなのでサイト全体に影響を与えるものではない。

④今後Page Experienceの重要性が高まってくる（Googleが公式で発表しているため）

上位表示されているサイトをチェックし、ユーザーがどんな事でストレスを感じているかを調査し、列挙してみると良いです。



#Core Web Vital
公式では
Webページを最適化することでユーザーの利便性が向上し、それがWebの発展やビジネスの成長にもつながると考えている
となっています。

Core Web Vitalを構成する3つの要素
①LCP(Largest Contentful Paint)
簡単に言うとページ表示速度のことを指します。
ページ読み込み速度は,2.5秒以内なら問題なし
スコアより表示速度の方が重要。

②FID(First Input Delay)
簡単にいうと操作性のこと
ユーザーが行う入力操作の反応の速さを指している。
ボタンやリンクをクリックするまでにやたら時間のかかるサイトは指標が悪い。

③CLS(Cumulative layout shift)
視覚要素に関する指標
突然クリックを誘発する広告等が表示されたり、追従するポップアウトなどは減点。

Core Web VitalとPage Experienceは酷似しています。
よって、Core Web Vitalを改善することによりPage Experienceを満たすことになります。

#Passage
セクション毎にページとして確認されますよということです。
なので、ページ内の関連性を確認されると意識してデザインを構成する必要があります。
（View作成時ブロックとして作成しないと適応されないので注意）

#BERT
もともと英語圏のみに提要されていたアルゴリズムですが、2019年より70言語に対応(日本語含む)
BERTはBidirectional Encoder Representation from Transformersの略。
検索クエリに適応
自然学習処理という技術の１つで、Wilipediaなどから得た大量のデータを学習モデルが事前学習し、文章理解や感情分析に応用できるというもの

Rankbrainと似ているが、Rankbrainはクエリだけでなくコンテンツにも適応されるのに対し、BERTは検索クエリだけに適応される。

単語レベルの検索クエリだけでなく文章レベルの検索クエリまで理解できるように進化している。

#Google3大アルゴリズム
200種類以上のアルゴリズムが存在すると言われているアルゴリズムですが、その中でも重要度の高いと言われている3大アルゴリズムは
・被リンク
・コンテンツ
・Rankbrain
です。これらについて解説していきます。

##被リンク
被リンクとは外部サイトから自分サイトへのリンクをはられたことを指します。
被リンク元のドメインエイジも考慮される。
「関連性」が重要（関連性の低いサイトから被リンクされても影響は少ない）
現在の被リンクは「量」より「質」が重要になっている。
権威性、関連性のない個人ブログの相互リンクはほとんど意味がなく、やりすぎるとスパム判定される可能性が高くなる。

##コンテンツ
コンテンツの指標
・独自性のあるコンテンツ
・被リンクがある
・質の高い費リンクが付いている（内部リンクを含む）
・ユーザーが検索した内容の悩みを解決するコンテンツ
独自性は、用語は独特な言い回しは関係ない。
例
カップラーメンの作り方と検索するとお湯を入れると書いてある記事が沢山出てくる→たくさんいらないので似ているコンテンツは上位表示されない

【注意する項目】
検索エンジンからのアクセスが多いページは質が高いと判断される。
誤字脱字は質がぐっと下がる。
使い勝手（レスポンシブ対応）などを考慮されている。
画像や動画にAltがついている。
コンテンツが整理されている。（図やグラフがある）
外部リンクが適切に使われている。

##Rankbrain 
Googleが開発したAIのことを指す
学習機能があり、検索クエリから検索意図を読み取り、最適なページを検索結果に表示する。
例
MOMOMO社のAAAAという名前のゲームを作成
最初検索エンジンではAAAAという名称が何なのかわからない

多数のユーザーが「MOMOMO社　AAAA」というワードで検索することで、AAAA=MOMOMO社のゲームだと認識するようになる
その後AAAAというワードだけで検索結果を表示されるようになる。

#直帰率と検索順位の関係性
直帰率そのものは検索順位に影響は及ぼさない。（Googleから公式で発表)
理由としては、1ページで解決した場合離脱するので
例
福岡　天気で検索
1ページで解決されたら離脱する

悪い直帰率が高い例
ページの読み込みが遅い
ユーザーの検索意図が解決されない

直帰率より重要なのがPogo Sticking

#Pogo sticking
検索結果が解決されないページを作った場合に次の記事に行ってしまうことを指す

例
福岡　ラーメン　美味しいで検索
適当な記事をクリック→記事の内容はラーメンにこれを載せたら美味しいと書かれた内容→検索ワードが解決していないので次の記事へ→その記事の順位が落ちる

#Dwell time
検索結果からやってきたユーザーが検索結果に戻るまでの時間を表したもの
ページ滞在時間とは違う(ページ滞在時間はSNSなどのユーザーも含んでいる)
Dwell timeは検索順位に影響を及ぼす。
Dwell timeはアナリティクスで見ることができない。
対策→検索結果を満たすコンテンツを作ること
1秒も保持できないCookieを永久的に保持する方法（ITP2.3対応）

# 概要
半永久的に保持してくれるCookieを作成しようとした時に、困ったことが起きた。
普通にCookieをセットしても、Safariだと1秒も保持せずにexpireされるという悲しき事態になっている。
原因は、Appleが発表したITP（Intelligent Tracking Prevention）というトラッキング防止機能のアップデートによるものだ。
現在、制限は厳しいのはSafariだけだが、他のブラウザでも近い将来同じ状況になる可能性が高いため、今のうちに対策をうっておく必要がある。
以下は、その対策である。

## 対策
## ① ❌3rd Party Cookie 　◎1st Party Cookie 
3rd Party Cookie の場合、即expireされる。
これに関しては、SafariだけでなくChrome（条件あり）とFirefoxでも即時消される。

したがって、1st Party Cookieで発行させる必要がある。
1st Party Cookieとは、cookieを発行するサーバーとcookieを埋め込まれるサーバーが同じである状態のcookieのことを指す。つまり、同じドメインである状態であるということだ。
逆にドメインが別の場合に発行されるcookieは、3rd Party Cookie と定義される。
![Screen Shot 2021-10-15 at 13.43.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553280/12054e33-ce5e-b0b3-6425-22cd3f339a3e.png)

## ② ❌jsからの発行  　◎サーバーサイドからの発行
①の対策を行うために、javascriptでcookieを発行する方法がある。
GTM（Google Tag Manager）や GA（Google Analytics）などはこの手法が使われる。
![Screen Shot 2021-10-15 at 16.50.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553280/79d255dc-4885-6fb2-7c97-aa569e1e6f80.png)
しかし、Safariだと1日もしくは7日間でexpireされる。
今回は半永久的に保持したいので、要件を満たすことができない。
そこで使用される方法は、サーバーサイドからCookieを発行する方法だ。
HTTPヘッダーには、Set-Cookieというサーバーサイド側からcookieを発行する手段がある。
サーバーサイド側からの発行の場合だと、ITPの制限はなく開発者側で自由に設定できる。
また、1st Party Cookieと定義されるためにSet-Cookieするサーバーが同ドメインにある必要がある。
2つのサーバーを同ドメインと判断させる方法は、サブドメイン化することだ。
もしブラウザを表示するドメインが**contents.com**ならば、**www2.contents.com**のようにレコード設定することで可能になる。
![Screen Shot 2021-10-15 at 16.51.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1553280/19c73e3e-d139-e96a-40ee-bbb830329ddd.png)



## ③ ❌CNAMEレコード 　◎Aレコード
②でサブドメイン化する時のレコード設定の方法として、CNAMEレコードとAレコードがあげられる。
それぞれのレコードの意味を簡単に説明すると、

- CANAMEレコード：正規ホスト名に対する別名を定義するレコード
- Aレコード：IPｖ4でホスト名とIPアドレスの関連づけを定義するレコード

しかし、CNAMEレコードで設定すると、Safariでは7日間しかcookieを保持できない。
したがって、Aレコードを使ってサブドメイン化をする必要がある。

# まとめ
ITP2.3までによると、以下を守るとcookieは開発者側で自由に設定できるため、結果的に半永久的の保持が可能である。

- 1st Party Cookie で定義されるように発行すること
- サーバーサイド側からcookieを発行すること
- Aレコードでサブドメイン化すること
jenkinsのvs-code-metricsプラグインが参照しているライブラリがcoreからなくなったとかなんとかで動かなくなっていた

ので、なんとかしてみた。

coreからなくなっている原因ははこのあたりを参照。
https://github.com/jenkinsci/jenkins/pull/5320

で、↑の対応の影響がvs-code-metricsプラグインにも出ているわけですが
それに対応してくれている人がいてpull requestを出している
https://github.com/jenkinsci/vs-code-metrics-plugin/pull/5

…のだけど本流にマージされていない。（2021-10-15時点）

ので、マージされてないけどソースを落としてきて自分でビルドして
vs-code-metrics.hpi を作ってみた。

https://onedrive.live.com/?cid=FC3E8944551460E4&id=FC3E8944551460E4%2112974&parId=FC3E8944551460E4%2112973&o=OneUp

そもそも、今後メンテナンスがあまりされないであろうプラグインっぽいのでご利用は計画的に…
railsチュートリアル第七章 プロのデプロイ

##プロのデプロイ

```
$ git add -A
$ git commit -m "Finish user signup"
$ git checkout master
$ git merge sign-up
```

###本番環境でのSSL
ユーザー情報が流出する可能性がある。
ネットワークに流れる前に情報を暗号化させる技術TLS（略称）がある。
今回はユーザー登録ページのためだけにSSLを導入できる。以下利点
・Webサイト全体で適用
・ログイン機構をセキュア
・セッションハイジャック（Session Hijacking）の脆弱性に対しても多くの利点

SSLを有効化するのも簡単です。production.rbという本番環境の設定ファイルの1行を修正するだけで済みます。
configに「本番環境ではSSLを使うようにする」という設定をするだけです

###演習
1.ブラウザから本番環境（Heroku）にアクセスし、SSLの鍵マークがかかっているか、URLがhttpsになっているかどうかを確認してみましょう。
確認

2.本番環境でユーザーを作成してみましょう。Gravatarの画像は正しく表示されているでしょうか?
作成　成功
エックスサーバーでPython(flask)を動かしてみた件

下記サイトに移動

[エックスサーバーでPython(flask)を動かしてみた件](https://pchanz.com/%e3%82%a8%e3%83%83%e3%82%af%e3%82%b9%e3%82%b5%e3%83%bc%e3%83%90%e3%83%bc%e3%81%a7pythonflask%e3%82%92%e5%8b%95%e3%81%8b%e3%81%97%e3%81%a6%e3%81%bf%e3%81%9f%e4%bb%b6/ "エックスサーバーでPython(flask)を動かしてみた件")
Backlog APIのリクエスト数制限に対処する

本日ご紹介するのは、職場で契約して利用しているBacklogのユーザーやプロジェクトの棚卸しの業務の中で遭遇した問題とその対処法です。

# Problem

実は結構以前、今年の1月にBacklog APIについて単位時間あたりのAPI要求数の上限値が設定されました。

制限はユーザーの単位で、1分あたりの要求数が一定値に達するとHTTPステータスコード429を返すようになる仕様です。アクセス元が異なったりAPIキーが異なったりしても、ユーザーが同じならまとめてカウントされるそうです。
コード429制限は60秒経過後に解除されます。
詳細は[こちらのニュース](https://backlog.com/ja/blog/backlog-api-rate-limit-announcement/)で案内されています。

前述の「棚卸し」作業では、過去プロジェクトのWikiや課題の情報をごっそりエクスポートするアプリケーションを実行する必要があり、このときAPI要求数の上限に達して問題に気がついたわけです。

# Solution

Backlog APIの公式のJava言語向けクライアント・ライブラリであるBacklog4Jは、今のところ、自動リトライの仕組みを持っておらず、「次にアクセスOKとなるまでの時間はこれくらい」という情報の提供しかしてくれないようです。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/ec4869b9-0be9-6836-1e32-31d7d9ad75ef.png)

というわけで、当座は、クライアントを利用するアプリケーション毎、それもクライアントを使ってAPIに要求をする箇所毎に対処する必要があるわけです。
BacklogClient を使用してAPIにリクエストを送信した時 `BacklogAPIException` がスローされたら、その `getStatusCode()` メソッドで得られる数値をチェックして、 `429` なら少し時間をいてから再実行する。こういうロジックを埋め込みます。
​​​​​​​面倒なことこの上ないですがしかたがありません・・・。

ご参考まで、今回は以下のようなヘルパー関数を書いて乗り切りました（Java8以前であれば再代入や条件分岐をたくさん含んだ気持ちの悪いコードになっていたことでしょう）：

```java
public static void main(string[] args) {
    final BacklogClient client = /* ...クライアント初期化コード... */;
    final Project project = tryRequest(() -> client.getProject("GISUI"));
    /* ...中略...  */
}
​
private static <R> R tryRequest(Supplier<R> codeCallsApi) {
  
    // トライの最大回数
    final int maxTryCount = 3;
    
    // 最大トライ回数に到達した場合にスローする例外を生成する関数
    final Supplier<RuntimeException> exception = () -> 
        new RuntimeException("try count has been exceeded.");
    
    // APIリクエストを試みる関数
    // 戻り値は3種類：
    //  (A)  APIから結果が得られた場合 Some(Some(R))
    //  (B)  APIからコード429が返された場合 Some(None)
    //  (C)  APIからコード429以外が返された場合 None 
    final IntFunction<Optional<Optional<R>>> doRequest = n -> {
        
        // 2回目以降の場合はトライ前にインターバルを置く
        if (0 < n) {
            System.out.println("pause for Backlog API usage limit.");
            trySleep(61 * 1000);
            System.out.println("resume. try count = " + n);
        }
        
        try {
            // Backlog APIへのリクエストを行う => (A)
            return Optional.of(Optional.of(codeCallsApi.get()));
            
        } catch (BacklogAPIException e) {
            System.err.println("error: " + e.getMessage());
            
            // ステータスコードをチェック
            // ステータスコードが429（単位時間あたりの要求最大数に到達）の場合、リトライを促す => (B)
            // ステータスコードが429以外の場合、リトライでは解決しないので中断を促す => (C)
            return e.getStatusCode() == 429  ? Optional.of(Optional.empty()) : Optional.empty(); 
        }
    };
    
    // トライして結果を得るためのストリームを生成
    // 有効な結果があればそれを返し、なければ例外をスローする
    // Streamは遅延評価されるので、ひとたびAPIから有効な値が得られたらその後のAPI要求は発生しない
    return IntStream.range(0, maxTryCount) // 0, 1, 2, ... 
            .mapToObj(doRequest) // API要求トライ
            .takeWhile(Optional::isPresent) // Some(Some(R))ないしSome(None) の間だけ繰り返す
            .map(Optional::get) // Some(...) を Some(R) ないし None に変換
            .filter(Optional::isPresent) // Some(R) のものだけ取り出す
            .map(Optional::get) // Some(R) を R に変換
            .findFirst().orElseThrow(exception); // 最初の要素を取り出す
}
```
【Vue.js】v-onについて


#はじめに
こんにちは！　松本　佑大（まつもと　ゆうだい）と申します！
今回はv-onについてアウトプットしていきます！


#v-onとは
v-onとはボタンをクリックしたり、スクロールなどのユーザーによる一連の挙動を『イベント』と呼びます。そして、それら様々なイベントに対応して発動させる処理のこと（関数）を『イベントハンドラ』と呼びます。
Vue.jsにおいて、イベントによってイベントハンドラを実行させるには、v-onを使用します。


#書き方
今回はボタン`click!`を押したら、現在の日時が表示されるプログラムを実行していきます。

```HTML:HTML
<button v-on:click="Onclick">
  Click!
</button>
<p>
 {{ now }}
</p>
```
```Vue.js
var app = new Vue({
    el:'#app',
    data:{
      now=''
    }
    methods: {
        Onclick: function() {
          this.now = new Date().toLocaleString();
        }
    }
})
```

`data`オプションに`now`プロパティ（`p要素`と同じもの）を設置します。
イベントハンドラのメソッド`methods`を定義していきます。内容は、”ボタンをクリックしたら`data`の`now`に現在時刻を代入する”というふうにします。それが上記になります。
それを`p要素 {{now}}`とHTMLに記述すれば出力されます。
出力結果が画像のようになります。

#ポイントまとめ
・`<button v-on:〇〇="〇〇〇">`を記述
・`<p>{{〇}}</p>`を記述
・メソッド`methods`を定義し関数の処理を書く。
・`data`に`{{〇}}`と共通のプロパティを記述する


#最後に
今回はv-onについてアウトプットしました。
今回の記事を読んで気になったこと、質問等あればコメント等頂けると幸いです。

今後ともQiitaにてアウトプットしていきます！

最後までご愛読ありがとうございました！
JSでクラスの位置を取得する

`nanika`はClass名
targetをconsole.log()で見てみると、`offsetTop`と`offsetLeft`で位置が確認できる

```js
scrollTab (): void {
    const target: any = document.getElementsByClassName('nanika');
    window.scrollTo({
        top: target[0].offsetTop,
        left: target[0].offsetLeft,
        behavior: 'smooth'
    })
}
```
Amazon Rekognition カスタムラベルのProject Arnの調べ方

Amazon RekognitionカスタムラベルをCLIとかSDKで使う場合にProject Arnをパラメータとして渡さないといけないんだけど、マネジメントコンソールに書いてない！

途中まで推測つくんだけど、最後の数値がわからない・・・

arn:aws:rekognition:ap-northeast-1:999999999999:project/#{プロジェクト名}/#{謎の数字・・・}

ということで、CLIで調べるしかなさそう

```describe.sh
$ aws rekognition describe-projects
{
    "ProjectDescriptions": [
        {
            "ProjectArn": "arn:aws:rekognition:ap-northeast-1:999999999999:project/rekognition_custom_label_project/9999999999999",
            "CreationTimestamp": "2021-09-09T09:09:09.090000+09:00",
            "Status": "CREATED"
        }
    ]
}
```
【Python】lambda関数の使い方


## はじめに
lambda関数(ラムダ式)、また無名関数と呼ばれています。
名前の通り、名前の無い関数です(笑)。
[前編](https://qiita.com/PuchiCorner/items/24da1162d591d943fcfb)と[前前編](https://qiita.com/PuchiCorner/items/d71033e903c27be874a7)の**leaky ReLU**と**ReLU**グラフを作成した時に、

```python
list(map(lambda x: relu(x), X))
```
このようなコードがあります。今回はそれについて話したいと思います。

## lambda関数
```python
lambda parameter(s): expression
```
- parameter(s): パラメーターが複数であれば、""**,**"" で区切りします。
- expression: 計算式です。

例:

```python
tashisan = lambda x, y: x + y
print(tashisan(2, 4))
"""
結果:
6
"""
```

## lambda関数+map関数
```python
map(lambda parameter: expression, iterable)
```
反復可能なオブジェクトの各要素に、特定の計算式を適用します。

- iterable: 反復可能なオブジェクトです(listとか)。
- parameter: 反復可能なオブジェクトの各要素です。
- expression: 各要素に適用する計算式です。

例えば、学生の成績を全員に20点追加しようとするなら

```python
student_scores = [20, 30, 40, 50]

score_up = map(lambda score: score + 20, student_scores)
print(score_up)
# <map object at 0x7f868734dd90>
```
:::note warn
score_upの戻り値はメモリのアドレスです。
:::
listの戻り値が欲しかったら、

```python
list(map(lambda xxx))
``` 
で書く必要があります。

もう一度試すと

```python
print(list(score_up))
"""
結果:
[40, 50, 60, 70]
"""
```

## ReLUグラフ作成時のコード
```python
import numpy as np

# 反復可能なオブジェクト
X = np.linspace(-10, 10, 100)

# 計算式
def relu(x) :
    return max(x, 0)
    
list(map(lambda x: relu(x), X))
```
説明:
-10~10の間の100個数値をそれぞれ**ReLU**に適用させて、
戻り値をlistに格納します。

**更新:** コメントのご指摘により、

```python
list(map(lambda x: relu(x), X))
```
は

```python
list(map(relu, X))
```
また

```python
[(relu(x) for x in X)]
```
に書けばいいです。

## lambda関数 v.s 普通の関数(function)
最後に、lambda関数と普通の関数を軽く比較します。

|  | lambda | function |
| -------- | -------- | -------- |
| 名前     | 必要ない     | 必要 (```def fun_name:```)    |
| 計算式     | 一行のみ     | 複数行可能  |
|戻り値|自動的に戻る|```return```というキーワード必要|





以上、簡単にまとめました。
# Dart VM上でFirebase Storageにアクセスする

[こちら](https://stackoverflow.com/questions/61835023/how-do-i-access-firebase-firestore-from-dart-vm-dart-integration-tests)とほぼ同じですが、scopesに`'https://www.googleapis.com/auth/cloud-platform'`を追加しないと403エラーが帰ってきて詰まってたので備忘録です

```dart 
void main() async {
  var json = {};
  var credential = await Credentials.fetch();
  var fbClient = FirebaseClient(credential);
  //データ.jsonに書き込み
  await fbClient.post(
     'https://firebasestorage.googleapis.com/v0/b/[ProjectID].appspot.com/o/データ.json',
      json);
}

class Credentials {
  static Future<String> fetch() async {
    var pk = await getPrivateKey();

    var accountCredentials = ServiceAccountCredentials.fromJson({
      'private_key_id': pk['private_key_id'],
      'private_key': pk['private_key'],
      'client_email': pk['client_email'],
      'client_id': pk['client_id'],
      'type': 'service_account',
    });

    var scopes = [
      'https://www.googleapis.com/auth/datastore',
      'https://www.googleapis.com/auth/cloud-platform'//stackoverflowとかだとこれはなかったけど、ないと権限が得られず403エラーを吐いてしまう
    ];

    var client = http.Client();
    var credentials = await obtainAccessCredentialsViaServiceAccount(
        accountCredentials, scopes, client);
    client.close();
    return credentials.accessToken.data;
  }

  static Future<Map<String, dynamic>> getPrivateKey() async {
    String jsonString =
        await File('/Path/to/firebase_private_key/keyfile.json')
            .readAsString();
    return json.decode(jsonString);
  }
}
```
pmmpをソースコードから実行する


# 環境
 - windows

# やり方

## pocketmine
まずpocketmineをclone。cloneするブランチやタグを指定してあげてください
`--recursive`つけないとあとから怒られるから注意
`git clone --recursive https://github.com/pmmp/PocketMine-MP.git -b [ブランチ名(4.0.0-BETA5とか)]`
そしたらこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241492/4cd9825f-5ae3-25a7-3e71-8c1e5341ed4f.png)

## php8のbin
[ここ](https://dev.azure.com/pocketmine/PHP-Builds/_build?definitionId=3&_a=summary)から持ってきます
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241492/44c741cb-6109-bc94-7646-1c9351681a7a.gif)
展開して中身の`bin`だけとりだして、PocketMine-MP以下に配置します
こんな感じなってると思います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241492/600670f6-dc0f-37fe-e929-af90b5065b44.png)


## composer
つぎに[ここ](https://packagist.org/)からcomposerダウンロードしてきて、`PocketMine-MP/`にcomposer.pharを入れます
![download_composer.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241492/9b19c17b-a676-738e-7c99-06643c3c723e.gif)

`D:\~~\PocketMine-MP\bin\php\php.exe D:\~~\PocketMine-MP\composer.phar install`を実行

↑のやり方だとdevチャンネルのcomposerらしく、問題が発生する場合があるとご指摘いただきました。
インスートーラーを使用するか、`https://getcomposer.org/download/`や`https://getcomposer.org/composer-stable.phar`から安定版がダウンロードできるようです。

## サーバーを起動
`D:\~~\PocketMine-MP\bin\php\php.exe D:\~~\PocketMine-MP\src\pocketmine\PocketMine.php`
【Laravel】RefreshDatabaseでデータがロールバックされない問題を解決する

## 問題
LaravelでMySQLのDBテストを書いていたら、RefreshDatabaseでロールバックされないデータが発生した。

## 原因
テストで使っていたシーダー内でtruncate()を実行していたため。

## 解決方法
truncate()を使用しない。

## 状況の再現
たとえばhogeシーダーでは、truncate()で最初にテーブルデータの全件削除を行って、つぎにデータを投入している。

```php:HogeTableSeeder.php
<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class HogeSeeder extends Seeder
{
    public function run()
    {
       DB::table('hoge')->truncate();
       DB::table('hoge')->insert(['name'=>'事前投入ほげほげ']);
    }
}

```

下記のようなDBテストで、RefreshSeederの実行＆シーダーでのデータの流し込みをしているとする。


```php:HogeTest.php
<?php

namespace Tests\Unit;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

use App\Hoge;

class HogeTest extends TestCase
{
    use RefreshDatabase; // テストごとにデータをリフレッシュする

    public function setUp(): void
    {
        parent::setUp();
        $this->seed(); // テスト開始時にシーダを実行する
    }

    public function testHoge1()
    {
        // hogeテーブルにデータを追加する
        $hoge = new Hoge();
        $hoge->name = "テストほげほげ";
        $hoge->save();
        // このテスト内ではデータは存在するはず
        $this->assertDatabaseHas('hoge', ['name' => "テストほげほげ"]);
    }

    public function testHoge2()
    {
        // 別のテストではtestHoge1()で追加したデータは存在しないことを期待している
        $this->assertDatabaseMissing('hoge', ['name' => "テストほげほげ"]);
    }
}
```
シーダーで流し込んだデータは全てのテストで共通して存在しており、各テストで追加したデータはそのテスト内のみで完結するように期待している。
しかしこのテストを実行すると、**1つめのテストで追加したデータが残ったままで、2つめのテストは失敗する**。

また、テスト終了後のテーブルの中身はシーディングデータ含めすべて残っている（ロールバックされていない）。

|id|name|
|-|-|
|1|事前投入ほげほげ|
|2|テストほげほげ|
|3|事前投入ほげほげ|



## RefreshDatabaseとtruncate()を同時につかってはいけない
`DB::table()->truncate()`はテーブルの全件削除のメソッドで、sqlのtruncateを実行する。
`db:seed`時に前回のシーディングデータを削除したいがために使用されていたようだった。

一方、RefreshDatabaseは`mirate:refresh`を実行し、トランザクションを貼って最後にロールバックするメソッドである。
これら２つが併用されるとどうなるかというと、下記の様になる。

--テスト開始--
1. `migrate:refresh`実行
2. トランザクッション開始
3. シーダー実行
4. truncateの実行（**暗黙的なコミットがはしる**）
5. テストメソッドの処理
6. tearDown()が呼ばれる
7. ロールバックができない
--テスト終了--

sqlで書くとこんなかんじ。

```sql
BEGIN;
TRUNCATE `test`.`hoge`;
INSERT INTO `test`.`hoge` (`id`, `name`) VALUES ('1', '事前投入ほげほげ');
INSERT INTO `test`.`hoge` (`id`, `name`) VALUES ('2', 'テストほげほげ');
ROLLBACK;
```
実行するとわかるが、トランザクション内でtruncateを実行するとcommitが走るので、その後のinsertで追加したデータは残ったままである。

## 解決方法 truncateを使用しない
`migrate:fresh --seed`すればいいだけなので、そもそもシーダーでtruncate()を呼ぶのはナンセンスである。
これだけのことを探すのにすごい時間がかかった。
参考：https://dev.mysql.com/doc/refman/8.0/ja/implicit-commit.html
高トラフィックアプリケーションでCloudRunの料金が半額以下になった件について

## 事の発端

2021年9月某日、[CloudRunに「CPUを常に割り当てる」オプションが追加されました。](https://cloud.google.com/blog/products/serverless/cloud-run-gets-always-on-cpu-allocation)↓
![CPUを常に割り当てる](https://cloud.google.com/run/docs/images/set-cpu-allocation.png)

大変驚くべきことに、高トラフィックを常にさばくようなインスタンスでは、このオプションをポチっと押すだけで料金が半額以下になります。

## 新しい料金体系の特徴

「CPUを常に割り当てる」オプションを有効化すると、**従来とは異なる料金表が適用されます**。
詳細は[公式ドキュメント](https://cloud.google.com/run/pricing#:~:text=CPU%20%E3%81%8C%E5%B8%B8%E6%99%82%E5%89%B2%E3%82%8A%E5%BD%93%E3%81%A6%E3%82%89%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AE%E6%96%99%E9%87%91)を参照してほしいのですが、従来のものと比較した際に特に注目すべき差分を以下に挙げてみます。

- 従来は100万req毎に発生していた「リクエスト料金」がかからなくなります
- CPU料金が1vCPUあたり月間62.208\$->46.656\$になります
- メモリ料金が1GiBあたり月間6.48\$->5.184\$になります
- アイドルインスタンスの概念が無くなり、コンテナ起動から終了までに使用したリソースが全て課金される

CloudRunをバッチ処理のワーカーとして利用する場合に、トリガーとなるリクエストを返した後でもCPUを利用して計算処理を行いたいというニーズに合わせたオプションなのですが。。。
「トラフィックを常時さばくようなアプリケーション」においてはコンテナは基本的に立ちっぱなしであり、箇条書きの最後のデメリットは完全に無視できます。
そのため、**有効化するだけで料金が安くなる夢のようなオプション**と言っていいでしょう。

## ではどれぐらい安くなったのか

CloudRunの料金は[公式の計算ツール](https://cloud.google.com/products/calculato)で算出できます。
(頑張って手作業で計算することも出来ますが、無料枠を考慮に入れる必要があったり結構難しいです。)

計算に必要な主なパラメータは以下です。

- インスタンスを動かすリージョン
- 1コンテナあたりのvCPU数(max:4)
- 1コンテナあたりのメモリ(max:8GB)
- 1コンテナが同時に処理できる最大リクエスト数, いわゆる同時実行数
- リクエストの平均処理時間
- 時間あたりのリクエスト数

今回はパラメータのうち上3つをTokyo, 4vCPU, 0.5GBに固定し、下の3つを変化させて料金比較を実施してみます。

### 同時実行数=40, リクエストの平均処理時間=20ms

![同時実行数=40, リクエストの平均処理時間=20ms](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957674/9c3e2cd7-46bf-2294-1ce6-040e5160335b.png)

- 従来料金/新料金 ≒ 13

### 同時実行数=40, リクエストの平均処理時間=100ms

![同時実行数=40, リクエストの平均処理時間=100ms](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957674/57e5e34b-594f-6fd1-b59c-3bbe76be1ae4.png)

- 従来料金/新料金 ≒ 3.5

### 同時実行数=10, リクエストの平均処理時間=20ms

![同時実行数=10, リクエストの平均処理時間=20ms](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957674/e09e0d1e-23ac-76a5-c6cb-e229f83b42a3.png)

- 従来料金/新料金 ≒ 4.1

### 同時実行数=10, リクエストの平均処理時間=100ms

![同時実行数=10, リクエストの平均処理時間=100ms](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957674/84e2d8cf-1975-c0e3-b73b-fbc0c257566c.png)

- 従来料金/新料金 ≒ 1.9

## 結果と考察

同時実行数が多ければ多いほど、リクエストの平均処理時間が小さければ小さいほど新しい料金体系の恩恵を受けられることが分かりました。

特に同時実行数=40, リクエストの平均処理時間=20msのケースは例えばGo製のwebサーバーなどであれば十分実現可能な設定であるにも関わらず、料金が1/13にもなるというのは驚きです。

Apache+PHP5のような同時実行性能が低く処理時間も遅いアプリケーションでは旨味は減るものの、そのようなケースであっても従来の半分程度になると考えられます。

### GKE vs CloudRun

またこれは余談ですが、いままで高トラフィックアプリケーションではGKEとCloudRunを比較した際にCloudRunが料金の面で大きく劣っていました。
ですが、この新料金体系の登場により関係が逆転する可能性が高いです。
(Todo: グラフを作る)

## まとめ

- CloudRunに「CPUを常に割り当てる」オプションが追加されました
- 高トラフィックを常にさばくアプリケーションでは料金が半額以下, 場合によっては1/13以下になります
    - GKEと比較した場合でも同等かGKE以下の料金になります

## こちらもオススメ

https://medium.com/google-cloud-jp/%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%83%AC%E3%82%B9-%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A-cloud-run-%E3%81%AB%E6%96%B0%E6%A9%9F%E8%83%BD-always-on-cpu-%E3%81%8C%E7%99%BB%E5%A0%B4%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-c88cd1114c60
過去の話題「スターリンソート」をVでやってみた

:::note alert
本投稿に記載されている非常に凶悪なソート手法は実際のプロダクトでは使用してはいけません。
:::

# スターリンソートとは
https://twitter.com/4116You/status/1155619860027547648

ソートされていない要素を**粛清**して強制昇順リストを生成する凶悪なソート手法を知ったので ~~話題の(ほんとか？)~~ V[^1]で実装してみました。

先駆者たち[^2][^3][^4][^5][^6]が他の言語で実装しており参考にしました。

# V[^1]で実装
コード

```go
pub fn stalin(src []int) []int {
    if src.len == 0 {
        return src
    }

    mut stalined := [src[0]] // スターリン済み配列

    for i := 1; i < src.len; i++ {
        if src[i] < stalined.last() {
            continue
        }
        stalined << src[i]
    }

    return stalined
}

fn main() {
    data := [1, 1, 4, 5, 1, 4, 8, 1, 0]
    println(stalin(data))
}
```
実行

```terminal
$ v run main.v
[1, 1, 4, 5, 8]
```
[^1]: [The V Programming Language](https://vlang.io) / [github.com/vlang/v](https://github.com/vlang/v)
[^2]: [計算量O(n)の画期的なソートアルゴリズムであるスターリンソートをHaskell で実装してみた #Haskell](https://qiita.com/Tatsuki-I/items/380d6bd06515b872b2b2)
[^3]: [計算量O(n)で噂のスターリンソートを実装してみた](https://qiita.com/MeilCli/items/721526d716851e92192a)
[^4]: [[Rust] スターリンソートと PartialOrd](https://qiita.com/osanshouo/items/1d4f56d93ee8ac8bdf55)
[^5]: [rubyでスターリンソートをやってみた（ブロック渡しも可能）](https://qiita.com/haru_pad/items/1598690e1105f3e33389)
[^6]: [話題の粛清ソートアルゴリズム「スターリンソート」をPythonで実装した](https://qiita.com/Sirloin/items/c9e5c74be3366df65bce)
エクセルでUTF-8/UTF-8NのCSVを読み込むときに、『このテキストファイルのデータは、1つのワークシートに入りきりません』と出るときの対処法

# Summary

エクセルでUTF-8/UTF-8NのCSVを読み込むときに、『このテキストファイルのデータは、1つのワークシートに入りきりません』と出るときの対処法

かなりはまったのでメモ

## env.

windows

```
> ver
Microsoft Windows [Version 10.0.19043.1288]
```

excel

```
Microsoft® Excel® 2016 MSO (バージョン 2109 ビルド 16.0.14430.20154) 32 ビット 
```

## CSV

csv is ...
  fenc is utf8 or utf8n
  ff is unix( LF )

```
col1,col2,col3
アイスクリーム,a,b
```

utf8(ef bb bf)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149269/03e75486-a574-f284-ab69-ba5029fbbde9.png)

utf8n
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149269/e5a36d37-7b79-db30-a04e-776cfe4e4a5d.png)



## 症状

データ > 外部データの取込み > テキストファイル

にて

CSVが読み込めない



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149269/cb900330-581c-3c24-6512-d5d97ad0d3a0.png)



## 原因

レコードの最初のフィールドが『アイスクリーム』（日本語）

## 対処

ダブルクオテーションで囲む

```
col1,col2,col3
"アイスクリーム",a,b
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149269/79b673d1-e68e-09ca-d7c8-9bb59d5f2658.png)


現場からは以上です( ´ー｀)ﾌｩｰ．．．
CakePHP3よく使ってるなと思うコマンドメモ


```php:Session.php
$Session = $this->request->getSession();
$Session->check('shikibetsu_name');
$shikibetsu_name = $Session->read('shikibetsu_name');
$Session->write('shikibetsu_name',data);
$SessionId = $Session->id;
```
```php:Table.php
use Cake\ORM\TableRegistry;
$CompaniesTable = TableRegistry::getTableLocator()->get('Companies');

//有無のチェック
$Company = $CompaniesTable->find()->where(['id' => $id])->first();
//firstを使う。get($id)だとない場合エラーになるので判定までいけない
if($Company){
//あった場合の処理
}else{
//なかった場合の処理
}

$Company = $CompaniesTable->newEntity($Data);//InsertEntity
$Company = $CompaniesTable->patchEntity($Company,$Data);//UpdateEntity

if ($Company->getErrors()) {
//バリデーションエラー処理
}

if ($Company = $CompnaiesTable->save($Company)) {
//save成功処理
}else{
//seve失敗処理
}

```

```php:Email.php
use Cake\Mailer\Email;
$Email = new Email('sakura');
$Email->setEmailFormat('text')
->setViewVars(['user_name' => $user_name, 'age' => $age]);
$Email->viewBuilder()->setTemplate('login');
$Email->setFrom(['notify@sample.jp' => 'なんとかメール配信システム'])
->setTo($mail)
->setSubject($title)
->send();
```

```php:redirect.php
use Cake\Routing\Router;
return $this->redirect(['controller' => 'dashboards', 'action' => 'login']);
```

```php:LayoutRender.php
$this->autoRender = false;
$this->viewBuilder()->setLayout('any_layout');
return  $this->render('any_template');
or
return  $this->render('any_template','any_layout');
```

```php:ajax.php
if (!$this->request->is('ajax')) {
 return new ForbiddenException();
}

$this->autoRender = false;

$ret = [];
$ret['error'] = [];
$ret['status'] = 'fail';

return $this->response = $this->response->withCharset('UTF-8')->withType('application/json')->withStringBody(json_encode($ret));
```
【Nuxt.js】ヘッドレスCMS（microCMS）の導入について

#はじめに
こんにちは。
こちらの記事では、Nuxt.jsでmicroCMSを導入する方法を記しています。
誤っている点がございましたらコメントいただけると幸いです。

##ヘッドレスCMSとは
>ヘッドレスの「ヘッド」は、ビュー（表示する画面）を指します。ヘッドレスなので、ビューの無いCMSということになります。

> 参照：https://blog.microcms.io/what-is-headlesscms/

WordPressのような管理画面（ビュー）がなく、APIからデータを取得して描画させることができる。既存サイトを残したままブログ機能を追加したいときなどに使用できる。

##実装手順
今回は日本製のmicroCMSを使って、APIからコンテンツのIDを取得する。

###1. Nuxtの新規プロジェクトとmicroCMSのコンテンツ作成
Nuxtの新規プロジェクトを作成し、microCMSのアカウントを登録する。今回使用するAPIの基本情報を入力、APIの型選択、APIスキーマの定義まで行う。
microCMSの詳しい記事は[こちら](https://blog.microcms.io/getting-started/)。

###2. APIの取得
Nuxtの新規プロジェクトのpages配下にあるindex.vueを下記のように編集する。

```javascript:script
<script>
import axios from "axios";

export default {
  async asyncData() {
    const {data} = await axios.get(
      'https://サービス名.microcms.io/api/v1/APIのエンドポイント',
      {
        headers: { "X-API-KEY": "APIキーを入力" }
      }
    )
    return data
  }
}
</script>
```
`サービス名`・`APIのエンドポイント`・`X-API-KEY`は、どちらもmicroCMSのAPIプレビューから確認できる。

```html:template
<template>
  <div>
    {{ contents }}
  </div>
</template>
```
templateに、マスタッシュ構文で`contents`を表示させることで、登録した全てのデータを取得できる。

###3. データ１件分のIDを取得
templateを以下のように書き換えることで、１件分のIDが画面に描画される。

```html:template
<template>
  <div>
    {{ contents[0].id }}
  </div>
</template>
```



#おわりに
ここまでmicroCMSの導入手順についてまとめました。
初めて導入する際はつまづく箇所も多いと思いますが、[公式サイト](https://microcms.io/)の記事を参考にしてみてください！
以上、最後まで読んでいただきありがとうございました！
Java - How to Set Difference Configuration Files for Log4j2

```java
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;

...
...
...

if (env.equals("DEV")) {
    setLog4j2ConfigFile("log4j2-dev.xml");
}

private void setLog4j2ConfigFile(String log4j2ConfigFile) throws URISyntaxException {
    LoggerContext context = (LoggerContext) LogManager.getContext(false);
    context.setConfigLocation(getClass().getResource(log4j2ConfigFile).toURI());
}
```

https://stackoverflow.com/questions/23200891/how-to-use-multiple-configuration-files-for-log4j2
SQLのサブクエリについて

### 今回のお題
今回のお題はSQLのサブクエリについてです。
いきなり微妙な話題ですね。

以下、目次です。
主目的が自分用のメモなのでやや冗長な部分もあるかもしれませんが、ご了承ください。

### 目次
- そもそもクエリとは
- サブクエリとは

### そもそもクエリとは
サブクエリの説明の前に、クエリとはそもそもなんぞやという話をします。
クエリとは、データベースから必要なレコードを取得するための命令文のことですね。

以下、クエリの一例です。

```SQL
SELECT * FROM users WHERE age >= 30;
```
上記のクエリでは、「usersというテーブルからageカラムの値が30以上のuserのみを選択し、そのユーザーの全てのカラムを表示しなさい」という命令になります。

では、次に本題であるサブクエリについて見ていきます。

### サブクエリとは
サブクエリとは「あるクエリの中で補助的に使用されるクエリ」のことを指します。
実物を見ていただいた方がわかりやすいと思うので、以下をご覧ください。

```SQL
SELECT name, age FROM users WHERE age >= (
    SELECT age
    FROM users
    WHERE name = "太郎"
);
```
上記のクエリにより、年齢が"太郎"以上のユーザーが全て抽出されます。
太郎の年齢を求めるために、where句の中で補助的にクエリが実行されているというわけですね。
### 注意点
サブクエリのカッコ内にはセミコロンはつけません。
メインの方のクエリの文末のみでOKです。
【個人開発】モノやサービスを供養できるアプリを作ってみた。【オマイリー】

## はじめに
![top-image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/870132/8e094d39-f9f2-fa91-6e7b-443b22c5c7c7.png)


>・買ったばかりのスマホを落として画面バキバキになってしまった
>・サポート終了になるInternetExplorer
>・元カレのくれたプレゼント

 「どうしよう…」

そのあと湧き上がる

「やり場のない気持ちをぶつけたい」

みなさんにもそんな時があると思います。

お世話になったモノやサービスに敬意を込めて供養してあげる。

とても慈悲深いアプリが出来ました。

https://omailly.jp/

## サービス概要

投稿されたタイトルをクリックすると、専用のお墓に見立てた位牌が鎮座しています。
![moko.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/870132/bcdcde41-963a-26bc-fc31-20246eed9e65.gif)

「御参り」ボタンを押すと黙祷タイムです。
![moko1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/870132/dc0c543d-7864-4972-dc5e-3d20482f1335.gif)


きちんと御参りができればTwitterシェア出来ます。

シェアすることで他の方から気持ちを可視化したと気付いてもらうことができます。

ヘッダーからタイトル検索もできます。
![スクリーンショット 2021-10-13 1.39.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/870132/9fa75f08-a5e5-0e63-169a-4bd93ae718f5.png)


https://omailly.jp/

# こだわったポイント
## 1.見た目

「供養」と聞くと思い浮かぶのは大抵の場合ですと神社・仏閣・お墓でしょう。

そんな厳かなイメージを崩さないためにカラーは黒を基調としています。桜も舞います。

## 2.形態素解析

特定の人の名前が入ると色々と問題になる可能性があるので【人名】はタイトル部分で対象外としました。

mecabというgemと、mecab-ipadic-NEologdというmecabのシステム辞書を用いています。

また、辞書に登録されていない珍しい名前の方を除外するため別途でcsvファイル作成し読み込んでいます。

参考: https://qiita.com/sho-jp/items/50243956373f21b1e138

![omailly_test3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/870132/63bfd727-0ce6-f7bc-5130-5b32fefae790.gif)


## 3.動的OGP出力

供養されたのが何なのかを分かるようにするために固定ではなく動的に反映される様にしました。

https://omailly.jp/posts/44

Cloudinaryを使っています。
参考: https://qiita.com/yuppymam/items/21a65d32fed9d7ecceba

---
#### 苦労したところ
- モーダル内のテキストを一定時間でフェードインさせる部分と文言のランダム化はJSですが、初めて見るメソッドだったり慣れない書き方だったので苦労しました。

- 人名を入力すると弾かれる部分はカスタムバリデーションを作成しました。

```ruby
class CheckPersonNameValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    names = tokenize(value)
    return if names.blank?

    record.errors[attribute] << "  #{names.join} 様が傷つきます。"
  end

  private

  def tokenize(value)
    nm = Natto::MeCab.new("-d #{Rails.root.join('dic/mecab-ipadic-neologd')} -u #{Rails.root.join('dic/userdic/user_dic_omailly.dic')}")
    names = []
    nm.parse(value) do |n|
      names << n.surface if n.feature.split(',')[2] == '人名'
    end
    names
  end
end

```

- ローカルでは問題なかったのですが、pushした時にmecabが見つからないエラーに悩まされました。
aptファイルがないよ！と怒られたり、インストール手順が悪いのかと思い`$ heroku run bush`でシェルに入りherokuのOSを確認してpathを通してみたり、herokuの[buildpack](https://github.com/heroku/heroku-buildpack-apt)なるものを使ってみたりしましたがうまくいかず…。

先輩エンジニアに「Dockerだといけるかも」とアドバイスをいただけたので、rootにDockerfileとheroku.ymlを設置することで解決しました。

#### 今後実装したいこと


- 焼香か線香のlikeボタン
- 投稿のジャンル分け

#### 主な技術

- Ruby 2.7.3
- Rails 6.1.4
- JavaScript
- jQuery

#### 主なGem

- cloudinary
- mecab
- natto
- pagy
- meta-tags
- rubocop

### おわりに

最後まで目を通していただきありがとうございました。
色々な方からアドバイスをいただけたり、一緒に考えてもらいながら作り終えることが出来ました。
本当に感謝しています。
これからも技術を追求してより良いアプリを作れるように頑張っていきます。
ありがとうございました。

twitter: https://twitter.com/Find_michi

お盆に間に合わなかった為、きちんと供養しておきます。

https://omailly.jp/posts/1
SpringBootの始め方

# はじめに
普段Javaのエンジニアですが、らしいことを全然かけてないなと思い。SpringBootでAPIを作るまでの簡単な流れを記事にしてみようと思いました。
やり方はこの方法でなくてもあると思いますので一例としてみていただければと思います。

# 前提
eclipseはすでに持っていることを前提としているため必要な方はeclipseを取得してから後続の作業を行ってください。
https://mergedoc.osdn.jp/

# spring initializr
以下のリンクからspring initializrを開いて諸々記載が終わったら「GENERATE」ボタンを押してください。
https://start.spring.io/

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524088/4df83b69-e331-722a-b2b4-8cd02f655b55.png)

特に何を作るという目的もないので、buildツールをGradleにだけ変えています。
パッケージ名やJavaのバージョン等にこだわりがあればそこは適宜読み替えていただければと思います。

**「GENERATE」ボタンを押すとzipがダウンロードできると思いますのでよき場所にダウンロードしたzipを解凍しておいてください。**

# Eclipseでのインポート
## インポートリンクを押下
人によってこのあたりの表示は違うと思いますが、プロジェクトのインポートを押してください。
![import.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524088/aea55931-d94f-6521-6fba-13c97ec4f1f7.png)

## Gradleから既存のGradleプロジェクトを選択
![gradle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524088/7337454e-6b41-cbe3-2f0f-2380c10e9945.png)

## ダウンロードしたファイルを参照して「完了」
![gradle_fill.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524088/91efc1d8-8bfd-b150-fa2d-c38d89596c94.png)

これでプロジェクトのインポートが終わります。


# Gradleの設定を修正
build.gradleにAPIとして実行可能となるように`org.springframework.boot:spring-boot-starter-web`を追加します

```gradle:build.gradle
plugins {
	id 'org.springframework.boot' version '2.5.5'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'
	// RestControllerを使えるようにするために追加
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
	useJUnitPlatform()
}

```

# コントローラーを作成
下記の通りコントローラを作成する
パッケージは適当に`com.example.demo.app.controller`としました。

```java:TestController.java
package com.example.demo.app.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

	@GetMapping("/test")
	public String test() {
		return "Hello World";
	}
}
```
# 起動

## プロジェクトで右クリック
![run_project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524088/e8d27c39-fad6-9d43-65ad-de452f4d392b.png)

## 実行にカーソルを合わせ「Spring Boot アプリケーション」を押下
![実行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524088/2979a6ff-d349-6e0f-8a15-f1ebe0051e0e.png)

![run_app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524088/c7923e04-7c83-1bd8-7377-0433ff17b4ac.png)

## コンソールを確認
起動が成功していたら下記のようにコンソールが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524088/2f278ad0-7fa7-cdec-7aad-132cc2a581e7.png)

# APIを確認
下記にアクセスしてみてください。
http://localhost:8080/test
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524088/5fb70a57-2fd3-a903-b8ff-377b23a5525d.png)

無事にAPIが呼べていることが確認できました。

# 終わりに
SpringBootを始めるのは難しいイメージがあるかもしれませんが、意外と簡単です。
是非是非導入を検討してみてはどうでしょうか？
SourceTreeでアカウントを切り替える方法

SourceTreeのユーザー切り替えについてです。
メモ書き程度なのであしからず。

##変更する場所
1. ツールバー>環境設定>一般
![スクリーンショット 2021-10-15 17.27.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896591/b8866ab4-dba9-fe82-b9e3-f06e5facda05.png)

2. ツールバー>環境設定>アカウント
![スクリーンショット 2021-10-15 17.28.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896591/b480502e-2670-e7d1-bb95-27eb2bd56626.png)

3. 各リポジトリの設定>高度な設定
![スクリーンショット 2021-10-15 17.29.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/896591/04824e0a-792b-5741-2677-3cd4e35dc048.png)

この3つを変更すれば大抵は大丈夫やろう。大丈夫大丈夫（適当）