OmniAICreator/Qiita-1.07M huggingface dataset:
【Spring Boot】 Using MySQL Database & BootStrap

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/5f35a4a2-777d-0ebb-f7cc-dcd91c5187ff.png" width="400">
　　**今回は、Spring initializrからプロジェクトを作成しました。**

#学べたこと
:star:　Spring initializrからプロジェクトを作成する
:star:　MySQLとの接続
:star:　クエリ情報の受け渡し
:star:　BootStrapの導入
:star:　Thymeleafの記述方法


#参考動画
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/foARzSz_1WU/0.jpg)](http://www.youtube.com/watch?v=foARzSz_1WU)
YouTube:https://youtu.be/foARzSz_1WU

#Software programs
>[Spring Tool Suite 4](https://spring.io/tools)
>[Bootstrap](https://getbootstrap.com/)
>[MySQL Database server](https://www.mysql.com/)

#完成:gift:
![2021-02-15_02h26_41.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/207ba957-41df-e66b-5556-9a71c897906a.gif)


#まとめ
今回苦労した点は、EditとDeleteボタンのクエリ情報の受け渡しの記述でした:pencil2:
下記の様に記述しました:star:

```html:index.html
<!-- Add new ボタン-->
<a th:href="@{'/new/'}">Add new</a>

<!-- Edit & Delete ボタン-->
<td><a th:href="@{/edit/{id}(id=${student.id})}" class="btn btn-primary">Edit </a></td>
<td><a th:href="@{/delete/{id}(id=${student.id})}" class="btn btn-danger">Delete</a></td>
```
今回登場したアノテーション
:hatching_chick:Entityクラスに登場
　　@Entity
　　@table
　　@Id
　　@GeneratedValue
　　@Column

:ear_of_rice:Repositoryクラスに登場
　　@Repository

:beer:Serviceクラスに登場
　　@Service
　　@Autowired

:video_game:Controllerクラスに登場
　　@Controller
　　@GetMapping
　　@RequestMapping
　　@PathVariable
　　@ModelAttribute

#最後に
次は、Spring Securityのプロジェクトを作成します。

次のプロジェクト：[【Spring Boot】 Registration and Login with MySQL Database, Bootstrap and HTML5, Spring Security](https://qiita.com/iwasaki-hub/items/d438a8675fb4060759cf)
Django3.1で任意のエラーページを設定する方法

# Django
Djangoでエラーページを設定する方法について。
「templatesフォルダにHTMLを入れるだけだよ。」という不十分な説明が聞こえてきたので、0から記述する。

## 環境
```
C:\2021006_django\django_app>python -m django --version
3.1.6
```

## 1.settings.pyで実行モードを変えよう

この時点でベーシックなエラーページに切り替わる。

```
DEBUG = False

ALLOWED_HOSTS = ["www.example.com"]
# ワイルドカードはセキュリテイ的に危険。
# ALLOWED_HOSTS = ["*"]
```

## 2.エラーページを作ろう
・ルートディレクトリにtemplatesフォルダを作成。
※Djangoにおけるルートディレクトリとは、manage.pyファイルが存在するディレクトリのこと。
・404.html といった規則でHTMLファイルを作成。

```
<html>
  <head>
  <meta charset="UTF-8"></meta>
  </head>
  <body>
  <section>
    <div class="error404">
        <h1>404 Page Not Found</h1>
        <p>URL {{ request.get_full_path }} は見つからないゾ☆。</p>
    </div>
  </section>
  <section>
      <p><a href="javascript:history.back()">&lt; Back</a></p>
  </section>
  </body>
</html>
```

## 3.settings.pyにテンプレートのパスを追加しよう
```
import os
TEMPLATES = [
    {
        ～
        'DIRS': [os.path.join(BASE_DIR, 'templates')], 
        ～
]
```
iosのSimulatorで@が打てない

## iosのシミュレーターで@が打てない
![スクリーンショット 2021-02-15 1.12.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/943089/7c06d9e8-7a65-7f95-a0a4-c70067bb0750.png)
`Simulator`を起動して左上の`I/O`をクリック。
そして、`Connect Hardware Keyboard`のチェックを外してまたすぐチェックをつける。

そうするとキーボードで打った@がSimulatorの方にしっかり反映されるようになります。
kodi で Youtube動画再生時に失敗する問題

## 【前文】
数日前から kodi で再生できない（エラーを吐く）Youtube動画がまた出てきた。
以前、Raspberry Pi のアップデートで同様の問題が発生したことがあったので、敢えてアップデートは行っていない。
従って、Youtube側の仕様変更の問題と思われる。

逆にアップデートを行っていないことが原因かもとアップデートを行うも（久しぶりのアップデートでかなりの時間を要したけど）改善せず。
エラーログの内容からぐぐり対応方法を探す。
キャッシュのクリアや、APIキーのクリア、再登録等が出てきたので実行するも解決せず。
プラグインは自動アップデート設定になっているが念のため明示的に手動でアップデート。やはり改善せず。

## 【結論】
以下のページに答えがあった。
[Invalid URL 'http___'_ No host supplied · Issue #10 · anxdpanic_plugin.video.youtube · GitHub](https://github.com/anxdpanic/plugin.video.youtube/issues/10 "Invalid URL 'http___'_ No host supplied · Issue #10 · anxdpanic_plugin.video.youtube · GitHub")

現象、ログの内容が一致するものの、去年の投稿。
既に解決済みならプラグインに修正が反映されている筈。
と思いつつ、下にスクロールすると、ここ数日の投稿で、また 一部の Youtube動画が再生できない問題が再発したとの報告が。
そして3日前に、中の人が修正版（テスト版）のプラグインをアップしていた。
今まさに進行中の問題だったのね。
早速テスト版プラグインを DL し、入れたところ問題は解決した。
いずれ正式なプラグインにも反映されると思われ。

## 【教訓】
解決方法をぐぐる、のではなくコミュニティで報告質問できるようになりたいもの。

それと心なしか kodi の動きが機敏になった（部分がある）。
キャッシュをクリアしたり、ゴミを消したからか。定期メンテナンスは必要だね。
#Rspec」での星レビュー記述方法

## Rspecでの星レビュー記述方法
`Ruby` `Ruby on Rails` `Rspec`
Rspecで星レビューの記述をする際にとても苦労したので備忘録として残しておきます。

##　星レビュー機能
![2021-02-15 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/946119/cdd0c8c4-4e50-b8d2-4cd0-1e58086cffcd.png)
Ratyを用いて口コミの星レビューをjQueryで実装しました。それぞれの項目の星マークをクリックする動作をさせたいので検証ツールで確認をします。
 

## ブラウザ検証

![2021-02-15 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/946119/097293dc-ecf1-cab0-aa70-c970411e5084.png)

## spec_rbのコード
```ruby:spec_rb
#findメソッドを用いて#review_star直下のimgのalt='5'を探してクリックします。
find('#review_star').find("img[alt='5']").click
```
## エラー
Capybara::ElementNotFound:
       Unable to find visible css "#review_star"

↑上記エラーで#review_starが見つかりませんと言われています。
この原因はfindメソッドではそもそもhidden_fieldは探せないからです。
※html上では確認はできますが、Rails上では見えていない状態になります。
そのため、visible: dalseをfindメソッドに付けると、hidden_fieldも探せる状態になります。

```ruby:spec_rb
 find('#review_star', visible: false).set(5)
```

## 最後に
私もプログラミングを始めてまだ3ケ月ですが、これから役立つような記事を書けるように頑張ります。
もし、上記内容に不備がありましたら、お申し付け下さい。
宜しくお願い致します。
AWSを使ってWordPress(ブログ)のWebサイトを構築してみた


#はじめに
AWSを勉強したいと思い、座学で頑張っていましたが、手を動かさないことの限界を感じ、手を動かして環境構築した結果を記します。第一弾となります。


#環境
Windows10
Tera Team

#やりたい事
EC2をwebサーバとしてWordPressにてブログ作成。
RDSを起動し、EC2とRDSを紐づけることでWordPressのDB参照先となる。
また構成はEC2一台、RDS一台のシングル構成である。

#構成

![ハンズオン1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609281/7cd8cad9-58f2-5281-6bbc-eeadf0294041.png)

作成ポイント
・RDSを作成するのにサブネットグループを作成する必要がある
・サブネットグループを作成するためにマルチAZ構成かつどちらのサブネットも2つずつ作成する

#躓いた点
![2021-02-14 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609281/08c75e31-b443-30cd-e740-4fb9a1a4b962.png)

こちらのパスワードの入力箇所で躓きました。
理由は下記のRDSのパスワード生成欄で「パスワードの自動生成」にチェックボックスを入れてしまい、入力すべきパスワードが分からなくなりました。こちらの問題は下記で解決出来ました。


![2021-02-14 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609281/f58d5abf-474b-f519-0de5-35ca7c79ac35.png)

こちらはRDSの画面で「database-1」を選択して変更を押すことで、ハンズオン通りに任意のパスワードを指定することが出来ました。
結果、WordPressも無事使えるようになりました。
（本来であれば、自動生成のパスワードでも出来るはずなので、自動生成のパスワード版の手順が分かればこの記事をアップデートしたいと思います）

#補足(AWS構成図作成ツール)
この記事を書くためにAWSの構成図作成ツールを探してたんですが、いいサイトがあったので共有します。
（もうご存じかもしれませんが…）

[オンライン作図ツールcacoo](https://cacoo.com/)

Awsの各ロゴのテンプレート等が充実していて非常に使いやすかったです。
また、UIが分かりやすいのですぐ使えました。
↓AWSのテンプレートはこんな感じ
![2021-02-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609281/43a4fe5b-7be4-dc2c-59ef-e1f3a87d9a11.png)

また自身のAWS環境を自動で構成図に反映する機能もあるのでとても便利です！！

[参考リンク：AWS構成図をCacooに自動で挿入する新機能をリリースしました！](https://cacoo.com/ja/blog/aws-architecture-import/)


#最後に
この記事は[Cloud Tech](https://aws-cloud-tech.com/)というAWS学習コミュニティの課題として作成しました。
この代表の方はYoutubeもやっていて、昔から存じていました。（今の自分の担当しているプロジェクトにおそらくいらっしゃった）

Youtubeでこのコミュニティを知って、無料体験版を試したところ、とても今の自分に必要な内容と思い、有料版のサービスに加入しました。
AWSの学習でお困りの方は是非体験版をやってみるといいかもしれません。
引き続き記事を上げていきます。
pythonで実行元スクリプトのファイル名を取得する方法



実行元のスクリプトを別のスクリプトで取得する方法。
\_\_main\_\_モジュールをimportして\_\_file\_\_を参照する。

```python
import __main__
print(__main__.__file__)
```

ファイル名だけ取り出したいときは以下のようにする。

```python
import os
import __main__
print(os.path.basename(__main__.__file__))
```

すぐ忘れるので備忘録として。
バリデーションのformatオプション

#WHY
今日は初めてformatオプションを使ったので、使う上で学んだことや調べたことをアウトプットしていく

----
##formatオプション
<b>withオプション</b>で与えられた正規表現と属性の値がマッチするかどうかを検証する。
以下のような記述をすることによって文字の種類を指定することができる。

```ruby
validates :name, format: { with: /\A[a-zA-Z]+\z/,message: "英文字のみが使えます" }
```

##正規表現
文字列の一部分を抽出・置換したり、文字列が制約を満たしているかを調べるための表現方法。

###[a-z]
角括弧[]を使用することで角括弧で囲まれた文字のうち<b>いずれか１つがマッチ</b>するかをチェックする。<br>[a-z]はアルファベットのaからzまでのいずれかにマッチという意味。

###\d
<b>数字を表す特殊文字</b>。特殊文字を使用する場合は直前に\を記述しなければならない。
[a-z\d]は英数字のいずれか１つにマッチという意味。

###{n, m}
直前の文字が少なくとも n 回、多くても m 回という<b>文字数の制約</b>を追加する。
例えば、{8, }は、直前の文字が少なくとも８回出現するものにマッチという意味になる。

###iオプション
大文字・小文字を区別せずに検索する。

### .
ハイフンやピリオドなど含めた全ての英数字において、どの１文字にもマッチ。

###+
直前の文字が１回以上の繰り返しにマッチ。

###アンカー
幅0の文字列にマッチ。幅0とは文字と文字の間、文字列の先頭、文字列の末尾、などを意味する。ある特定の条件を満たす「位置」にマッチ。

|メタ文字|説明|
|:--:|:--:|
|\A|文字列の先頭にマッチ|
|\Z|文字列の末尾にマッチ、<br>ただし文字列の最後の文字が改行ならばそれの手前にマッチ|
|\z|文字列の末尾にマッチ|

------
正規表現を確認できるサイトがありました！
https://regexper.com/
こういうので遊びがてら使っているとだんだん使い方が身についていきそうですね！
Leap MotionでGoogleEarthProするまでの話

LeapMotion 使って
GoogleEarthPro(パソコン版)を操作できると[聞いた](https://qiita.com/chelcat3/items/6c2626a4a58fe298bda0)ので
やろうとして、つまづいた話。

##動作環境
つまづいたけど操作は無事にできました。
動作環境(2021/2/14時点)

|環境 | ver. |メモ|
|:-:|:-:|:-:|
| LepaMotion  |  4.1.0  |最新|
|  Windows10 | 1909  |---|
|  GoogleEarthPro | 7.3.2  |※つまづきポイント|

##つまづきポイント
GoogleEarthPro最新版(7.3.3)では操作できませんでした。
[古いバージョン](https://support.google.com/earth/answer/168344?hl=en)をインストールする必要がありました。

###NGテイク
[公式](https://www.google.com/intl/ja/earth/versions/#earth-pro)からGoogleEarthProをインストール
→7.3.3(64bit)
→Leap Motion 反応せず（NG）

↓

###OKテイク
[ヘルプ](https://support.google.com/earth/thread/85091672?hl=en)にならって[最も古いバージョン](https://support.google.com/earth/answer/168344?hl=en)をインストール
7.1.8(32bit)
→Leap Motion 反応しました。（OK）

---
その他、上位のバージョンも試してみました。

| ver. | 結果 | 備考 |
|:-:|:-:|:-:|
|7.3.3(32bit)   | NG  |  最古が32bit版だったので試したけどNG |
|7.3.1(64bit)   | OK  | デバイス抜き差し/アプリ再起動  |
| 7.3.2(64bit)  |  NG | デバイス抜き差し/アプリ再起動  |
|  __7.3.2(64bit)__ |__OK__| __PC再起動__  |
| 7.3.3(64bit)  |   NG| デバイス抜き差し/アプリ再起動/PC再起動  |

結果として、冒頭の構成で動作確認ができました。

##余談
[GoogleEarthStudio VR](https://twitter.com/tomo_/status/1360720327530086401?s=20)も面白そう
【rails】CSSでplaceholderの文字サイズを変更する方法

CSSでplaceholderの文字サイズを少し小さくしたい！って思ったことはありませんか？
通常のやり方でクラスを指定してfont-sizeプロパティを使用してもうまくいかず。。。
解決策は簡単なことでしたが備忘録として投稿します！

#ビュー
```ruby:view.html.erb
<%= f.text_field :name_or_comment_or_cooking_method_cont_any, placeholder: "料理名等で検索", class: "search-field" %>
```

#CSS
```css:css.scss
.search-field::placeholder {
  font-size: 12px;
}
```

適用したいクラスに対し上記のように記載すればplaceholderの文字サイズのみ変更できます。

#最後に
バックエンドのエンジニアを目指していますが、フロントエンドもできるようになりたいな〜って思っています。
これから就活が始まる、頑張ろう。。。
[Ruby on Rails] 商品のインスタンス変数


備忘録書いていきたいと思います！


まず学習して知ったことは、
**インスタンス変数**、すなわち**＠items**(仮)の数え方は
<h4>『配列』

として数えること。

そう
インスタンス変数の数え方は<h4>『配列』desu!!


大事なことなので２回書きました。

全くその事実を知らなかった自分は中々エラーが解けず苦労しました。


　　
　　
<h3>（例）

　　
もし、**＠itemsが空（nil）だった場合**の記述はこんな感じになります。

![スクリーンショット 2021-02-15 0.22.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078698/0a451d77-08a3-27b3-ae3b-370193f36a45.png)

よくよく考えたら、確かに配列だわ！と納得しました。
きちんと覚えておこうと思います。
Visual Studio Code の Power Shell をアップグレードする方法

Visual Studio Code のターミナルを表示すると Power Shell のアップグレードを促すメッセージが表示されるようになりました。
そのままでも利用できますが毎回表示されるメッセージがうっとおしいのでアップグレードしちゃいましょう！

![vscode-upgrade-powershell_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/ea38d51d-6d6d-4dfe-bc11-1497f18cfb59.png)

## 最新版の Power Shell をダウンロードする

[PowerShell/PowerShell](https://github.com/PowerShell/PowerShell#get-powershell) からインストーラーをダウンロードします。

* 64bit 版 Windows：Windows (x64)
* 32bit 版 Windows：Windows (x86)

LST (Long Term Support) 版をインストールしました。

![vscode-upgrade-powershell_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/688f7f83-3338-be25-7d87-d9d827cb4aad.png)

## Power Shell をインストールする

ダウンロードしたインストーラーを起動してインストールします。
全部 `Next` を押しました。

![vscode-upgrade-powershell_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/72609fdd-8fa0-a4e8-8def-85116b1d9921.png)

![vscode-upgrade-powershell_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/0fa7bb5b-cad4-31d5-c2ce-142c7eafc5c8.png)

![vscode-upgrade-powershell_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/d31b282e-ba8f-0743-e58d-da88596b45f0.png)

![vscode-upgrade-powershell_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/34c8c40a-a9ba-8a7f-c8ac-54aa0e3575a5.png)

![vscode-upgrade-powershell_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/30a23127-07c2-d8a3-37a7-4331ada8798a.png)

![vscode-upgrade-powershell_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/8e473ec2-5d37-c3f8-cea6-af0d862066f4.png)

## Visual Studio Code を再起動する

Visual Studio Code を再起動しターミナルを表示すると…
Power Shell のバージョン番号が変更されています。
アップグレードを促すメッセージも消えました！

![vscode-upgrade-powershell_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/b45925f4-217f-a450-b64e-e6cfa656dea9.png)
Visual Studio Code で新しい Power Shell を利用する方法

Visual Studio Code のターミナルに表示される

「新しいクロスプラットフォームの PowerShell をお試しください」

というメッセージがうっとおしいので表示されないようしちゃいましょう！

![vscode-new-powershell_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/d5cab434-2cea-57b9-144d-df9f0a5b8c48.png)

## メッセージが表示される原因

Visual Studio Code のターミナルは、デフォルトでは Power Shell で実行しており、Power Shell のバージョンが古い場合にこのメッセージが表示されます。
そのため新しい Power Shell をインストールすれば表示されなくなります。

## 最新版の Power Shell をダウンロードする

[PowerShell/PowerShell](https://github.com/PowerShell/PowerShell#get-powershell) からインストーラーをダウンロードします。

* 64bit 版 Windows：Windows (x64)
* 32bit 版 Windows：Windows (x86)

LST (Long Term Support) 版をインストールしました。

![vscode-new-powershell_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/5ddaa73d-a45a-0505-5779-5f3895bc6abf.png)

## Power Shell をインストールする

ダウンロードしたインストーラーを起動してインストールします。
全部 `Next` を押しました。

![vscode-new-powershell_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/7bb591b9-b6fc-49ca-3c05-b74781022f38.png)

![vscode-new-powershell_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/6e134362-ff90-2c9d-6f90-3f022282dbca.png)

![vscode-new-powershell_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/56d2e8eb-7c7a-8d97-f259-7cc1bcc068d7.png)

![vscode-new-powershell_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/ce0899fe-a51e-70e8-6e7f-3b75b5e251c3.png)

![vscode-new-powershell_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/138d3e05-5d7a-fae9-42f4-d339dadd5305.png)

![vscode-new-powershell_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/85f92225-86ea-6db6-83e5-9f7f56a15694.png)

## Visual Studio Code で利用する Power Shell を変更する

新しくインストールした Power Shell は Windows に最初からインストールされている Power Shell とは別のプログラムとしてインストールされます。
インストールした Power Shell を利用するためには Visual Studio Code の設定を変更する必要があります。

ターミナル上部のプルダウンをクリックし、「既定のシェルの選択」をクリックします。

![vscode-new-powershell_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/9f30d7fd-9fa7-ed36-550b-14b1b7434b04.png)

表示されたコマンドパレットから `PowerShell C:\Program Files\PowerShell\7\pwsh.exe ` を選択します。

![vscode-new-powershell_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/dd20fd48-fe11-f768-a3ba-845a06367915.png)

## Visual Studio Code を再起動する

Visual Studio Code を再起動しターミナルを表示すると…
「新しいクロスプラットフォームの PowerShell をお試しください」
というメッセージが表示されなくなりました！

![vscode-new-powershell_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492675/65ca8807-a603-1b2f-3aff-fa6693850cc2.png)
Spring Boot(Spring MVC)利用時のTest構成メモ

# 前書き
普段、何気なくSpring Boot(Spring MVC)のテストを設計・実装してるのですが  
初心「そういえば我々、今どんなTest構成なんだっけ？(特に、利用ブラウザ)」を忘れがち。

関連クラス辿ったので、備忘しておくもの。

# 前提
[公式Doc1](https://spring.pleiades.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-with-mock-environment)や[公式Doc2](https://spring.pleiades.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests)に則って、自動構成に任せたMVC Testを書いていること。

すなわち、`@WebMvcTest`周りを利用したテスト実装であること。

# 本題:Test構成の仔細
結局、[MockMvcWebDriverAutoConfiguration](https://spring.pleiades.io/spring-boot/docs/current/reference/html/appendix-test-auto-configuration.html#test-auto-configuration)が設定されている。

同Configurationクラスのコードは[こちら](https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/MockMvcWebDriverAutoConfiguration.java)。

実装より、以下2つの条件いずれも満たしていれば、同クラス配下のBean登録を試みる。

1. ライブラリ`org.openqa.selenium.htmlunit.HtmlUnitDriver`が利用可能
1. プロパティ`spring.test.mockmvc.webdriver.enabled=false`が明示されていない

---
Bean登録について条件と、概要は以下。

1. ` WebDriver` , `MockMvcHtmlUnitDriverBuilder`いずれのBeanとも登録が無い場合
  `MockMvcHtmlUnitDriverBuilder`をBean登録する。  
  その折に、`browserVersion.CHROME`指定の[LocalHostWebConnectionHtmlUnitDriver](https://github.com/spring-projects/spring-boot/blob/ca9b583c7d46d478ec6970ceb483705fe5845546/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/htmlunit/webdriver/LocalHostWebConnectionHtmlUnitDriver.java)インスタンスを用いる。  
  判りやすく言えば「Selenium利用するHtmlUnit」となる。
1. `WebDriver`は登録が無いが、`MockMvcHtmlUnitDriverBuilder`はBean登録してる場合  
  `HtmlUnitDriver`をBean登録する。  
  その折、`MockMvcHtmlUnitDriverBuilder`を利用。  
  加えて、SecurityContextに従う必要あれば、設定済みExecutorを`HtmlUnitDriver`に反映してくれる。

---

# 補足 : HtmlUnit(含:Selenium)設定に手を入れたい場合の流れ
まず初めに、`WebDriver`や`DriverBuilder`周りの、`Configurer`や`Customizer`利用を考えるべし。
続いて、`DriverBuilder`や`HtmlUnitDriver`Beanを、自前で登録。
SwiftUIでカラーをアニメーションする方法

# 概要
SwiftUIで画面表示後にカラーが変化するようにしたかったので、その方法を記載します。
【デモ】
<img width="150" alt="colorAnimationDemo.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224949/50a96189-5761-cb31-f13f-b3b0fca9395f.gif">

# 方法
`@State`でcolorを監視できるようにします。
画面の表示時に`onAppear`が呼ばれるので、
`withAnimation `を用いて、colorプロパティを指定した秒数をかけて変化させます。

```swift
import SwiftUI

struct ContentView: View {

    @State private var color: Color = .blue

    var body: some View {
        Rectangle()
            .onAppear(perform: {
                // 画面が表示されたら3秒かけて赤色に変化させる
                withAnimation(.easeInOut(duration: 3), {
                    color = .red
                })
            })
            .foregroundColor(color)
            .ignoresSafeArea()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```

ボタンを押したらアニメーションで色を変化させたいとかであれば、`onChange`で検知すればできそうですね！
Anacondaを使わずにデータ分析・機械学習の環境を構築する

# はじめに

Anacondaをインストールせずにデータ分析・機械学習の環境を構築する手順について解説します。

## 前提条件ついて

本記事では、

- venvを用いて仮想環境を構築する
- 深層学習で主に使用されるパッケージはインストールしない
- スクレイピング、自然言語処理、画像処理等で使用されるパッケージはインストールしない

という前提で手順を記載しています。
手順の中でも触れていますが、他にインストールしたいパッケージがあれば個別にインストールしてください。

## 動作確認している環境について

また、本動作を確認している環境は、

- Ubuntu 20.04
- Python 3.9.1 (Pyenvでインストール)

ですが、

- 特定のOSに依存した操作は行っていませんので、Windows、macOS、LinuxいずれのOSでも構築可能
- パッケージでインストールしたPythonでも同様の手順で構築可能

です。
ただし、`python`と`pip`はご使用の環境によってコマンド名が違う場合があるので、環境に合わせて読み替えてください（`pip`ではなく`pip3`になっている、など）


# 構築手順


## 1. 仮想環境をインストールするディレクトリを作成する

仮想環境を使って独立したPython環境を作成し、そこに必要なパッケージをインストールします。
まずは仮想環境を作成するディレクトリを作成します。ここではディレクトリ名を`jupyter`にしていますが、少なディレクトリに好きな名前で作成してください。

```shell
$ cd /path/to
$ mkdir jupyter
$ cd jupyter
```

## 2. 仮想環境をインストールする

作成したディレクトリにVirtualenvで仮想環境を作成します。ここでは`venv`という名前(2つある`venv`のうちの後ろの方)で仮想環境を作成していますが、好きな名前で作成してください。

```shell
$ python3 -m venv venv
$ ls    
venv
```

次に、仮想環境を有効化します。先ほど作成した仮想環境の名前を`venv`以外の名前にしている方は以下のコマンドの`venv`の部分を作成した名前に変更してください。

```shell
$ source venv/bin/activate
```

これ以降、仮想環境を有効化している状態で操作しています。違いがわかるようにプロンプトを`$`から`(venv) $`に変えています。

## 3. 仮想環境を最新化する(pip、setuptools)

```shell
(venv) $ python -V           
Python 3.9.1
(venv) $ pip -V   
pip 20.2.3 from /home/xxx/jupyter/venv/lib/python3.9/site-packages/pip (python 3.9)
```

パッケージをインストールする前に`pip`と`setuptools`を最新バージョンにアップグレードします。

```shell
(venv) $ pip install --upgrade pip setuptools
```

念のため、`pip`のバージョンを再確認します。

```shell
(venv) $ pip -V                              
pip 21.0.1 from /home/xxx/jupyter/venv/lib/python3.9/site-packages/pip (python 3.9)
```

`pip`のバージョンが`20.2.3`から`21.0.1`にバージョンが上がっています（使用してるPythonのバージョン、作業時期によってバージョンアップの有無、バージョンアップ後のバージョンは変わります）。

## 4. データ分析・機械学習に必要なパッケージをインストールする

では、機械学習に必要なパッケージをインストールします。
ここではデータ分析、機械学習に最低限必要そうなパッケージのみをインストールしています。他に使いたいパッケージがあれば別途インストールしてください。

```shell
(venv) $ pip install ipython numpy pandas matplotlib seaborn scikit-learn jupyterlab
```

インストール時に出力されているログを見てインストールに成功していることを確認してください。

これでこのディレクトリがデータ分析・機械学習を行う環境になります。

## 5. JupyterLabを起動する

では、JupyterLabを起動してみます。

```shell
(venv) $ jupyter lab
```

ブラウザにJupyterLabが表示されれば正しく構築できています。

今後、データ分析・機械学習を行うときは、このディレクトリに移動して有効化後にJupyterLabを起動してください。

```shell
$ cd /path/to/jupyter
$ source venv/bin/activate
(venv) $ jupyter lab
```

## (おまけ)仮想環境から抜ける方法

作業後にターミナルを閉じているならあまり必要ありませんが、仮想環境から抜ける方法についても紹介しておきます。
(実用上忘れていても問題なることは殆どないので神経質になる必要ありません)

```shell
(venv) $ deactivate
$ 
```

# 最後に

PyenvでAnacondaをインストールしていたのですが、どうやらcurlコマンド等がAnacondaでインストールした方を参照してしまい、Anaconda以外に切り替えたときにcurlコマンド等が使えなくなるという事象に陥りました。
修正しているような記事も見かけましたが、実際には修正されていなかったので、Anacondaを使わずに環境構築する方法を検討しました。
ただし、Anacondaをパッケージでインストールすれば、`system`を選択することで使用可能になるので、どちらかというとすべてのPythonをPyenvで管理したい、という方やAnacondaを使いたくない（有償版を使わないといけない、などの理由から）方向けの記事になります。
KiCadで作成したデータをもとに自動配線するツール

KiCadで自動配線するのに使用するFreerouting.exeは2021年2月14日現在、以下にあります。
ググってもGithubにあるという記事が出ますが、そこにはありません。
<a href="https://freerouting.mihosoft.eu/">Freerouting.exe</a>
PHP5上級試験/準上級試験の上級合格に挑戦(1)　試験研究

# 自己紹介と受験背景
+ 学生時代から今まで、プライベートでの活動の一つとしてWebサイトを作り運用してきている
+ 本来の業務では使ったことはないが、フロントエンドエンジニアで必要なことは一通りできる
+ その一方で、入社後からずっとマクロを学び業務としてきたマクロ屋
+ 現在の環境でPHPについて学ぶ必要があり、その過程で自然と上級試験を受けることに
+ PHPは関数とか書き方とかはマクロと似ているところがあり、基礎のところは理解している
+ しかし業務ではまだまだ使えていない
+ PHP7初級試験は合格済（上司がPHP5でなくて最新が７だからそれを受けて、と言われた）
+ その後、PHP７上級は２０２１年２月の時点でまだなく、PHP５上級を受けることに
+ 一応準上級までは合格済（かなりぎりぎり）
+ 文法とかクラスとかは一応理解はできているが、DBや拡張モジュールとかになるとわからない
+ 試験を受ける以上、暗記はしたが、知識として理解できているとは言い難い
+ たとえばどんなときにこの知識を使えばいいのかイメージできていない
+ PHPをきっかけにバックエンドエンジニアとしての転向を目指している
+ PHP５上級試験対策として、Qiitaで、PHP5上級試験で出題されるテーマを掘り下げまとめることにした
+ PHP5上級試験合格以降も身につけたことをまとめていきたい

# PHP5上級試験/準上級試験概要と参考書（リンク）
+ [PHP5上級試験/準上級試験概要 | PHP技術者認定機構](https://www.phpexam.jp/summary/expert/)
+ [徹底攻略 PHP5 技術者認定 [上級] 試験問題集 [PJ0-200]対応 | Amazon](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-PHP5-%E6%8A%80%E8%A1%93%E8%80%85%E8%AA%8D%E5%AE%9A-%E8%A9%A6%E9%A8%93%E5%95%8F%E9%A1%8C%E9%9B%86-PJ0-200/dp/4844334670/ref=sr_1_1?ie=UTF8&qid=1389697123&sr=8-1&keywords=%E5%85%AC%E5%BC%8F%E3%80%80PHP%E3%80%80%E4%B8%8A%E7%B4%9A)
+ [プログラミングPHP 第3版 | Amazon](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0PHP-%E7%AC%AC3%E7%89%88-Kevin-Tatroe/dp/4873116686/ref=pd_sbs_1?pd_rd_w=gwxuQ&pf_rd_p=051ec0f2-89dd-40f5-9dc7-0162d5cbdbb9&pf_rd_r=0A7QNERRJYZ63TM4NCQG&pd_rd_r=a63ede9c-dda6-44a3-b5cc-6c0d3dc7d6b2&pd_rd_wg=PzJCy&pd_rd_i=4873116686&psc=1)

 
※ PHP技術者認定機構のページの模擬問題や黒本の仕上げ問題は解いて、模擬問題や黒本の仕上げ問題を参考に、どのような形で出題されるか理解しよう
※ Tipsからの出題など、隅を突くような問題が多いと思うので、なぜバツになるのか、なぜ丸なのかなど、理由までしっかり説明できるようになろう
※ どちらにしても４章以降のテーマを暗記ではなく、本当の意味で、理解しないと話にならない

# PHP５上級試験合格体験記（リンク）
+ [PHP技術者認定試験上級に合格するためにやったことをご紹介！ | 意識の高い時に雑記](https://lifehackdev.com/ZakkiBlog/articles/detail/web14)

※ 調べた限り、勉強した内容を書いて、受けますとして終わっているものや、結果的には準上級までしか合格してない人が多く、意外と合格した人のが１人と少なかった
※ 黒本でいう３章〜１３章を満点で、７割取れるらしい
※ メソッドを覚えておかないときつい、という感想があったが、同感
※ できればコードまで書いて、実践で使えるようになっておきたい
※　もし他にも合格者の記録があったらおしえてください

# PHP５上級試験出題範囲（PHP技術者認定機構のページより抜粋）　※黒本

| 目次| 出題割合     |
|:----|:------------|
| １章 PHPについて |0 |
| ２章 PHP言語の基本 |0 |
| [３章 関数](https://qiita.com/Atsulabo/items/1697299314441ff22105)|0.02 |
| ４章 文字列|0.02 |
| ５章 配列|0.04 |
| ６章 オブジェクト|0.1 |
| ７章 ウェブに関するテクニック|0.12 |
| ８章 データベース|0.08 |
| ９章 グラフィック|0.04|
|10章 PDF|0.04|
|11章 XML（＆XML系で追加された関数） |0.06|
|12章 セキュリティ|0.12|
|13章 アプリケーションに関するテクニック|0.08|
|14章 PHPの拡張|0.04|
|15章 WindowsでのPHP|0.02|
|予備 SPL（Standard PHP Library）/日付クラス/PEAR（管理系のコマンドなど） |0.04|
|予備 名前空間/クロージャー/リフレクション/Late Static Binding|0.04|
|予備 JSON|0.02|
|予備 PDOとネイティブモジュールの違い/mysqlndドライバについて|0.04|
|予備 正規表現（pcre, posix, mbstring）|0.02|
|予備 APD/Xdebug/memcache|0.04|
|予備 フィルター|0.02|

※ こないだ受けた準上級止まりだったところを分析したところ、メインだったところは半分にも満たず、逆に予備の方で１００％正答率になっているところがあった
※ よく出題されるのは、３章〜１３章らしいが、関数や文字列・配列ともに、他の章と絡んで使われたのを見ているので、３章〜１３章は出題割合が少ない章でも、まんべんなく勉強するといいはず

# まとめ

+ 黒本３章〜１３章を中心に不明点を理解しながらまとめる
+ 合格記にあるように関数のメソッドや値、実例などはしっかり暗記
+ 模擬問題・黒本の模擬試験はかならずやり、出題はどのようにされるか研究し、回答できるようにする
+ 今ここで限界を超えろ、それしか道はねぇ（by「BlackClover」ヤミ団長）

#今後の記事
+ ３章〜１３章を中心に不明点を理解しながら１記事１テーマでまとめていく
オライリーのWeb API The Good Partsまとめてみた⑤~設計変更をしやすいWEB APIを作る~

## 設計変更のしやすさの重要性
- WEBアプリケーションの変化によってAPIの改修が発生する
- 一度公開したWEB APIの仕様を変更するのはいずれにせよ問題が発生する危険性がある
## APIをバージョンで管理する
- 全く異なるURIでAPIを公開すると、更新を重ねるたびに何が最新なのかがわかりにくくなってしまう
- ソフトウェア同様バージョン番号を降っていくのが一番わかりやすい
- バージョン番号をどのような形式で表すかについてはいくつかの方法が議論されている

## URIのバージョンを埋め込む
```
例
■Tumblr
http://api.tumblr.com/v2/blog/good.tumblr.com/info
```
### バージョン番号をどうやってつけるか
- しっかりとしたルールがあるわけではないが、整数でカウントアップしていくのが定石
## バージョンをクエリ文字列にいれる
```
例
■netflix
http://api-public.netflix.com/catalog/titles/series/70023522?v=1.5
```
## メディアタイプでバージョンを指定する方法
- クライアントからのリクエストにバージョン番号を含むメディアタイプをAcceptヘッダーに入れてサーバに送信する
```
例
Content-Type: application/vnd.example.v2+json
```

## 結局どれがいいのか
- URIのパスにバージョンを埋め込む

## バージョンを変更する際の指針
- APIのバージョンを増やすことは、公開する側のメンテナンスコストも、利用するクライアントのコストも増やすことになるので、できる限りバージョンをあげないにこしたことはない
- 後方互換性を保つことが可能な変更は可能な限り同じバージョンでのマイナーバージョンアップで対応し、バージョンをあげるのはどうしても後方互換性を保ったまま修正を行うことが難しい変更を加えなければならない時にのみバージョンをあげるべき

## まとめ
- APIのバージョンの更新は最低限に止め、後方互換性にも注意する
- APIのバージョンはメジャーバージョンをURIに含める
- APIの提供終了時はすぐに終了するのではなく、最低６ヶ月は公開を続ける
【Spring Boot】 RESTful CRUD API

#RESTとは
RESTとは「Representtational State Transfer」の略で、分散システムのためのアーキテクチャーです。
ネットワーク経由で外部のサーバーにアクセスし、必要な情報をしゅとくするような仕組みを作るのに利用される考え方です。
また、このRESTの考え方にしたがって設計されるシステムを「RESTful」と表現します。

#参考動画

[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/3-5e5cXfwrU/0.jpg)](http://www.youtube.com/watch?v=3-5e5cXfwrU)
YouTube:https://youtu.be/3-5e5cXfwrU

#Software programs
>[Java Development Kit](https://www.oracle.com/java/technologies/javase-downloads.html)
>[Eclipse IDE](https://mergedoc.osdn.jp/)
>[MySQL Database server](https://www.mysql.com/)
>[curl](https://curl.se/)

#完成:gift:
>MySQLサーバーから情報を取得することができました:v:

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/28b3e5b2-c5d4-db88-6924-39b206512d32.png" width="800">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/3b43b997-0ec7-70e6-dcd2-f12743c607a7.png" width="600">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/fc94220d-c471-c8f2-2408-2d4fe0198186.png" width="600">

#まとめ
今回登場したアノテーション
:hatching_chick:Entityクラスに登場
　　@Entity
　　@table
　　@Id
　　@GeneratedValue

:ear_of_rice:Repositoryクラスに登場
　　@Repository

:beer:Serviceクラスに登場
　　@Service
　　@Autowired

:video_game:RestControllerクラスに登場
　　@RestController
　　@GetMapping
　　@PostMapping
　　@PutMapping
　　@DeleteMapping

#最後に
海外のTeck系動画はとても参考になります:video_camera:
初めて見るソースコードにも触れることが出来るので、学びの多い内容でした:blush:

次のプロジェクト: [【Spring Boot】 Using MySQL Database & BootStrap](https://qiita.com/iwasaki-hub/items/541ad66b62083e05da62)
オライリーのWeb API The Good Partsまとめてみた②~レスポンスデータの設計~

# レスポンスデータの設計
- データフォーマットはJSONをデフォルトとする

## JSONPの取り扱い
- JSONP = JSON with Padding
    - JSONにそれをラップするJavaScriptを付け加えたもののことをさす
```
callback({'id':123, 'name': 'Koh'})
```
## データの内部構造の考え方
- APIのアクセス回数がなるべく減るように設計する
- そのためにはそれぞれのAPIのユースケースを考えることが重要になる
- レスポンスの内容をユーザーが選べるようにする
```
/api/users/12345?fields=name,age
```
## エンベロープは必要か
- エンベロープはAPIのデータ構造の文脈では、全てのデータを同じ構造で包むことをいう
```
{
    "header": {
        "status": "success",
        "errorCode": 0
    },
    "response": {
        "id": "123",
        ・
        ・
    }
}
```
- メタデータも含んだ形で全てのAPIが同じデータ構造を返すために実際のデータを包むための構造のことをエンベロープという。
- HTTPがエンベロープの役割を果たしていて、ステータスコードでクライアント側はエラーを判別できるように、メタデータを改めて返却するようなデータは冗長な表現になってしまうため、やるべきではない
- データ階層をフラットにするべきかどうかはケースバイケースだが、単に複数項目をまとめたいがために階層構造にしてしまうのはあまりメリットがない
```
 # 階層的に表す場合
{
    "id": 2234,
    "name": "ueda",
    "profile": {
        "birthday": "1994-02-11",
        "gender": "male",
        "age": 22
    },
    ・
    ・
}

# フラットな構造
{
    "id":　"2234",
    "name": "ueda",
    "birthday": "1994-02-11",
    "gender": "male",
    "age": 22
}
```
- なるべくフラットにすべきだが、階層化した方が良い場合もある。

## 配列とフォーマット
- 結果一覧など、APIを配列で返却したいケースがある。
- APIのレスポンスを、そのまま配列を返す方法と、レスポンス全体をオブジェクトにしてその中に配列をいれる方法がある。

```
# 配列をそのまま返す
[
    {
        "id": "2234",
        "name": "ueda"
    },
    {
        "id": "2235",
        "name": "matsuda"
    },
    ・
    ・
]

# 配列をオブジェクトで包む
{
    "friends": [
        {
            "id": 2234,
            "name": "ueda"
        },
        {
            "id": 2235,
            "name": "matsuda"
        }
    ]
}
```
1. レスポンスデータが何を指しているのかががわかりやすくなる
2. レスポンスデータをオブジェクトに統一することができる
3. セキュリティ上のリスクを避けることできる
    - jsonインジェクションのリスクを避けることができる
    - jsonインジェクション：script要素を利用してJSONを読み込むことでブラウザに他のサービスのAPIが提供するJSONファイルを読み込ませ、その内容を不正に入手する手法

## 　レスポンスデータの設計
- APIは内部で持っているDBのテーブル構造をそのまま反映したものである必要はない
- (これは例えば友達一覧テーブルがユーザーIDだけを含んでいるからAPIではそれだけを返します！という考え方がNGという話で、DBがたまたまその画面に必要なデータをちょうどよく揃えているのであればそれで問題ない)
- この場合はユーザー検索と同じデータ構造を返す、ということをして「ユーザー情報はこういうデータです」というのをデータ構造として定義してあげると、クライアント側では同じコードを処理できるので、楽に作業を進めることができる。
- そのAPIのユースケースを考え、ユーザーが最もシンプルに扱うことができる設計を目指すのが大事。
## エラーの表現
- ステータスコードでエラーを表現する

|  ステータスコード  | 意味 | 
| ---- | ---- | 
|100 |情報| 
|200 |成功 | 
|300|リダイレクト|
|400|クライアント起因のエラー|
|500|サーバーサイドに起因するエラー|


- クライアントからのリクエストが成功した時しか200を返してはいけない
## エラーの詳細をクライアントに返す
- エラーの内容を返す方法は2つある
    - HTTPレスポンスヘッダに入れて返す方法
        - 独自に定義したヘッダ項目を用意して情報をいれる
    - レスポンスボディで返す方法
        - レスポンスボディとして、エラー時専用のデータ構造を用意して、そこにエラー情報を格納する
- 世間的にはレスポンスボディにデータをいれる方式をとることが多い。
## エラー詳細情報には何をいれるべきか
- エラー詳細コード
- 詳細情報へのリンク
- エラーの際にHTMLが返却されることを防ぐ

## まとめ
- JSON、あるいは目的に応じたデータ形式を採用する
- データを不要なエンベロープで包まない
- レスポンスをできるかぎりフラットな構造にする
- 各データの名前が完結で理解しやすく、適切な単数複数が用いられている
- エラーの形式を統一し、クライアント側でエラー詳細を機械的に理解可能にする。
そうだ、SQLの勉強をしよう⑩

#はじめに
〇〇句や関数がたくさんあり、そろそろ覚えられない…
今回は、グループ化について学びました。

##グループ別に集計したい
例えば、
「教科ごとに平均点を出す。」
「家計簿で支出金額を費目ごとに合計値を出したい。」
などです。

グループ化とは、
「何でまとめるか」
ということです。

そのようなときは、
GROUP BY句を使います。

```sql
SELECT 列名
FROM テーブル名
GROUP BY まとめる列名
```
「まとめる列名」に記述した列名でまとめられます。
先の例で言うと、
「教科」ごとの部分です。
ちなみに、カンマで複数列を指定することで、それらの組み合わせでまとめられます。
具体的には、
「男性、英語の平均点」
「女性、英語の平均点」
みたいに、2以上の要素でグループをつくるということです。


##集計関数をつかうには…
命令には、順番があります。

1. 検索
2. グループ化
3. 集計
4. 集計結果絞り込み

です。
WHERE句は「1.検索」に対して、処理を行うので、WHERE句には集計関数を使うことができません。
そんなときは、

###HAVING句

HAVING句は集計した結果に対して処理を行います。そのため、集計関数を記述することができます。
HAVING区の記述はGROUP BY句よりも後です。
Laravelでダミーデータ(Factory&Faker) が日本語化できない時の対処法

初学者です。エラー解決を軽めに発信していきます。

#開発環境
PHP 7.3.9
MAMP 5.7
Mysql 5.7.26
Laravel 6.20.7


#問題

Laravelで日本語のダミーデータを作成しようとして、config/app.php内で、

```php:config/app.php
'faker_locale' => 'ja_JP',
```

と記入したんですが、なぜか'ja_JP'としているのに英語でダミーデータが作成されてしまいました。
今までは全て日本語化できていたのに...

#対処法

まあ単純に考えて、英語ではあるけどダミーデータは作成されているから、FactoryやFaker、Seederのファイルには問題はないはずなので、config自体の変更が反映されていない可能性がありますね。

調べてみると、
**「開発環境でconfigファイルを編集したらキャッシュをクリアしないとキャッシュが反映されてしまう」**
らしいです。

```
$ php artisan config:clear
```

ターミナルでキャッシュをクリアしてからダミーデータを作成したら日本語化できていました！
よかった！！
オライリーのWeb API The Good Partsまとめてみた①~エンドポイントの設計とリクエストの形式~

# エンドポイントの設計とリクエストの形式
## APIとして公開する機能を設計する
- 下記のような機能をもつSNSサービスがあるとする。
    1. ユーザー登録、編集
    2. 友達の検索、追加、削除
    3. 友達間でのメッセージのやりとり
- シンプルなAPIを設計するのなら、サービスが利用するDBのテーブルを直接操作するようなものを作ることが考えられるが、SQLをただ包んだだけの設計では使いやすいAPIにはならない。
- そんなAPIではデータが内部的にどのように格納されているか、どういうリレーションを持っているかを理解していないと使えないし、内部構造を公開することがセキュリティ上のリスクがある。
- 公開するAPIがどのように使われるかのユースケースを考えることが必要である。
- 今回は上記のアプリを例に、モバイルアプリ向けAPIに必要な機能を検討する。
## モバイルアプリケーション向けAPIに必要な機能
- アプリの画面とその遷移がどのようになっているかを検討する。
- ログイン
    - ユーザー登録
    - 友達の近況一覧
        - ユーザー情報の表示と編集
        - 友達の近況一覧
            - 近況の投稿
            - やりとりしたメッセージ一覧(編集、削除可能)
                - メッセージ投稿
        - 友達一覧
            - 友達追加と検索
- 画面遷移を元に、どんな機能をAPIとして提供しなければならないかを考える
    - ユーザー登録
    - ログイン
    - 自分の情報の取得
    - 自分の情報の更新
    - ユーザーの情報取得
    - ユーザーの検索
    - 友達の追加
    - 友達の削除
    - メッセージの投稿
    - 友達のメッセージの一覧取得
- リストと表を比較しながら、過不足を確認

## APIエンドポイントの考え方
- WEB APIにおけるエンドポイントとは、APIにアクセスするためのURIのことをさす
- 覚えやすく、どんな機能をもつURIなのかが一眼でわかるように設計する
    - 短く入力しやすい
    - 人間が読んで理解できる
    - 大文字小文字が混在していない
    - 改造しやすい
        - あるURIから他のURLが想像できる
        - 例) /item/111の111を123に変更すればitem_codeが123のデータが得られそう
    - サーバー側のアーキテクチャが反映されていない
        - URIに/phpなど、バックエンドでどんな言語が使用されているかという情報はユーザーに必要ない
        - アーキテクチャの推定が容易になり、攻撃の対象になりかねない。
    - ルールが統一されている

## HTTPメソッドとエンドポイント
- サーバー側の情報を取得するために使われるのがget
- サーバー側の情報を更新するために使われるのがpost

## APIのエンドポイント設計

|  目的  |  エンドポイント | メソッド
| ---- | ---- | ---- |
|  ユーザー登録 | /users   | post     |
|  ユーザー一覧取得 | /users | get
|自分の情報の更新|/users/:id|put/patch|
|ユーザーの情報取得|/users/:id|get|
|友達の追加|/users/:id/friends|post|
|友達の削除|/users/:id/friends/:id/friends|delete|

## リソースにアクセスするためのエンドポイントの設計の注意点
- 複数形の名刺を利用する
    - 単数形でも見た目に意味はわかるし、単一の情報を取得する際などの例外はあるが、複数の情報を取得する=データの集合体を扱う処理のため、複数形の方が適切とされる
    - getやpostなどHTTPメソッドが動詞であり、その目的語として機能することがもっともシンプルに行いたいことを表すことができる
    - 動詞はあまりエンドポイントには入れない
- 利用する単語に気を付ける
- スペースやエンコードを必要とする文字を使わない
- 単語をつなげる必要がある場合はハイフンを利用する

## 検索とクエリパラメータの設計
- クエリパラメータは、膨大な検索結果を「絞り込んで」表示するのに有効な手段
## クエリパラメータとパスの使い分け
- 一意なリソースを表すのに必要な情報かどうか
- 省略可能かどうか

後日加筆修正して再投稿
WEB情報を集める必要があったのでスクレイピング入門

## はじめに
pythonはほとんど使ったことなかったけど、この動画が参考になりました。
https://www.youtube.com/watch?v=LgZ8Li97yoM&t=1660s

上記の動画に倣ってjupiter labで一通り実行すると、仕組みがわかりました。

## やりたかったこと
WEBサービスのFAQ情報を集める。

## 実現方法
質問回答ページのURLを一覧化して、pythonにインポートし、ページごとの回答をCSV形式でエクスポートする。

## URL一覧

|質問分類１    |質問分類2     |質問              |URL           |
|:----------:|:----------:|:----------------:|:------------:|
|アイテムについて|アイテムについて|サンダルについてしりたい！|https://xxxxxx |
|...|...|...|...|

## コード
コメント部分は自分の解釈

```python
from bs4 import BeautifulSoup
import urllib.request as req
import time
import pandas as pd
import os
import csv
import codecs

#FAQ掲載ページのURL一覧をCSV形式ファイルでインポートする
csv_file = open("./FAQ_suzuri.csv", "r", encoding="utf-8", errors="", newline="" )
f = csv.reader(csv_file, delimiter=",", doublequote=True, lineterminator="\n", quotechar='"', skipinitialspace=True)
header = next(f)

# インポートしたCSVファイルの３番目のカラムにあるURLを配列に読み込みます
url_list = []
for row in f:
    url_list = url_list + [row[3]]
for url in url_list:
    # urllib.request.urlopen(url)で、URLアクセス時のレスポンス情報を取得
    response = req.urlopen(url)
    # レスポンス情報をBeautifulSoupオブジェクトに変換
    parse_html = BeautifulSoup(response,'html.parser')
    # FAQの質問が格納されている要素を取得（クラス名がarticle-titleの要素）
    question_list=parse_html.find_all(class_="article-title")
    # FAQの回答が格納されている要素を取得（クラス名がarticle-bodyの要素）
    answer_list=parse_html.find_all(class_="article-body")
    ans = []
    # 取得した回答ごとに、要素の中のPタグを収集
    for i, x in enumerate(answer_list):
        temp = ""
        # １つの回答にある１つ以上のPタグを配列として取得し、tempに格納
        for y in x.find_all('p'):
            temp = temp + y.text + '\n'
        ans = ans + [temp]

    #cp932形式で処理できない文字コードによりエラーが出るため、例外処理を記載
    # 処理名をerr、処理内容を無名関数lambdaで記述（引数e,戻り値('', e.end)）
    codecs.register_error('err', lambda e: ('', e.end))
    # 取得したデータがUTF-8形式の文字コードだが、エクセルで編集したいためcp932形式でデータを取得する。
    # ファイルに書き込み（ファイル形式：CSV、文字コード形式：cp932、書き込み形式：追記）
    with open('faq_suzuri_scraping_output.csv', 'a', encoding='cp932', errors='err') as f:
        writer = csv.writer(f)
        for i, q in enumerate(question_list):
            # 質問と回答を書き込み
            # 質問のHTML要素からテキスト部分を抜き出し、スペースと改行コードを除外
            writer.writerow([q.text.replace(' ', '').replace('\n',''), ans[i]])
```

## output

faq_suzuri_scraping_output.csv

|サンダルについてしりたい！|S=2xcm・M=2xcm の2サイズ展開となっており、ソールは.xxxxxx|
|:-:|:-:|
|...|...|

## 最後に

本当は、URL一覧の取得から目的のFAQテキストの取得まで全部自動でやりたいけど今回はここまで。
UbuntuでVPN Gatewayへ繋げる

# 事前準備
## net-toolsインストール（無かったので）
```sh
apt install net-tools
```
## VPN Serverを決める
https://www.vpngate.net/ja/

## 自分の環境のデフォルトゲートウェイを調べる
```sh
ip route show | grep default
```
# 導入作業
## ダウンロードと起動
### VPNClientダウンロード
https://www.softether-download.com/ja.aspx?product=softether

※CPUはご自身の環境のものを。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/868e8ba3-b394-e536-90db-3f80f2da113e.png)

### tar.gzファイルを解凍

```sh
tar -xzvf ダウンロードファイル
```
### make
解凍ディレクトリへ移動し、make

```sh
make
```

### VPN Client 起動

```sh
./vpnclient start
```

### VPNサーバへのスタティックルートを追加
```
oute add -host [事前準備で選択したVPNGateサーバーhost] gw [先程調べた今のゲートウェイIP]
```

## VPN Client設定
### コンソールへ

```sh
./vpncmd
```

### 仮想NIC作成
```
NicCreate tun0
```

### 仮想NIC有効化
```
NicEnable tun0
```

### VPN設定追加
```sh
AccountCreate vpngate0 /SERVER:[事前準備で選択したVPNGateサーバーhost:TCPポート] /HUB:VPNGATE /USERNAME:vpn /NICNAME:tun0
```

### 匿名ログイン有効化
```sh
AccountAnonymousSet vpngate0
```

### VPN接続
```
AccountConnect vpngate0
```

### exit
```
exit
```

## terminal上で作業
### ifconfigで追加した仮想LANカードを確認
```
ifconfig
```
追加したdevice（vpn_tun0）がみえるはず。

### dhclientでip取得
```
dhclient [device名]
```

### default route削除
※ 事前にデフォルトゲートウェイをメモっておくこと。私はdefaultを消さずとも目標は達成できた。
route delete default

### backupコマンド例
```
route add default gw 192.168.1.1 dev enp7s0
```
`192.168.1.1`がデフォルトゲートウェイ、enp7s0が通常使っている有線LANデバイス名。

### IP確認
https://www.cman.jp/network/support/go_access.cgi

### 参考
#### 
ほぼこちらのサイトの引用です。
http://rauq04.blogspot.com/2014/02/linux-softether-vpn-client-vpngate.html
#### VPN Gate 
[VPN Gate](https://www.vpngate.net/ja/)

### softether download
[softether download](https://www.softether-download.com/ja.aspx?product=softether)
無線LAN調査まとめ

TODO 未完成状態

# 概要

|種類 |周波数帯/GHz |最大速度/bps |規格策定 |メモ |
|:---:|:---:|:---:|:---:|:---:|
|IEEE802.11a |5 |54 M |1999
|IEEE802.11b |2.4 |11 M |1999
|IEEE802.11g |2.4 |54 M |2003
|IEEE802.11n |2.4/5 |600 M |2009
|TODO acとか |||

|周波数/GHz |メリット |デメリット|
|:---:|:---:|:---:|
|2.4 |障害物に強い TODOなぜ？ |同じ周波数帯を使用する機器が多い=干渉が多い TODO干渉の仕組み |
|5 |無線LAN専用なので他の機器との干渉が少ない |障害物に弱い TODOなぜ？ |

## 2.4 GHz
13チャンネルある．各チャンネルは5MHzごとに離れている
ただし無線LAN通信の帯域幅は20MHzあるため，隣のチャンネルと干渉している
= 干渉防止のためにはある程度話して設定する必要がある

## 5 GHz
それぞれ下記のチャネルグループとチャンネルを持つ
W52は36/40/44/48のチャンネル
W53は52/56/60/54のチャンネル
W56は100/104/108/112/116/120/124/128/142/136/140のチャンネル

気象レーダと同じ周波数帯を使用しているため，W52/53は野外での使用が禁止されている．
W56は使用許可されているが，開始前に１分間のレーダ電波の検知を行って検知されなければ通信ができる．

W53は屋内でのみ使用できるが，１分間のレーダ検波は必須になる．

# 物理層


# 参考

https://hytec.co.jp/useful/wireless5451
docker-compose up ができない(buildできない)

```
docker-compose up --build
```
でビルドしようとしたが下記のようなエラーが出た。

```
ERROR: for phpmyadmin  Cannot create container for service phpmyadmin: Conflict. The container name "/phpmyadmin" is already in use by container "〇〇". You have to remove (or rename) that container to be able to reuse that name.

Creating mysql       ... 〇〇". You have to remove (or rename) that container to be able to reuse that name.

ERROR: for mysql  Cannot create container for service db: Conflict. The container name "/mysql" is already in use by container "〇〇". You have to remove (or rename) that container to be able to reuse that name.

ERROR: for phpmyadmin  Cannot create container for service phpmyadmin: Conflict. The container name "/phpmyadmin" is already in use by container "〇〇". You have to remove (or rename) that container to be able to reuse that name.

ERROR: for app  Cannot create container for service app: Conflict. The container name "/laravel" is already in use by container "b035ca2af11bfd74a1b04d341cd1ac0075b4301bdb484a598167f1db2b869b1a". You have to remove (or rename) that container to be able to reuse that name.

ERROR: for db  Cannot create container for service db: Conflict. The container name "/mysql" is already in use by container "〇〇". You have to remove (or rename) that container to be able to reuse that name.
ERROR: Encountered errors while bringing up the project.
```

既存のコンテナ名と重複してしまうためビルドできないということなので

```
docker rm $(docker ps -aq) --force
```

でコンテナを一掃してから、再度ビルドするとうまくいきました
Navberが動作しない。ドロップダウンが動かない。

##問題発生##
bootstrapのNavberのドロップダウンリストがうまく動かない。
レスポンシブルで画面を小さくすると、nav-itemが表示されない。消えてしまう。

##結論##
navbar-lightを消していたので動かなかった。

CSSでいじったりする際に消してしまっていた。

```html

//１行目のnav class内の navbar-light が必要。消してはだめ
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Navbar</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
      <a class="nav-item nav-link active" href="#">Home <span class="sr-only">(current)</span></a>
      <a class="nav-item nav-link" href="#">Features</a>
      <a class="nav-item nav-link" href="#">Pricing</a>
      <a class="nav-item nav-link disabled" href="#">Disabled</a>
    </div>
  </div>
</nav>
```
[CakePHP] AuthComponentのidentifyメソッドの中身の流れをざっくりと見ていく

この記事ではCakePHPのAuthComponentのメソッドであるidentifyメソッドの中身の中身をざっくりと見ていきます。

### identifyメソッドとは

> リクエスト中の認証情報を使用してユーザーを識別するために、 $this->Auth->identify() を 手動で呼ぶ必要があります。

> ユーザーを認証する際には、設定されている認証オブジェクトを設定された順にチェックしていきます。 あるオブジェクトでユーザーが識別できたら、以降のオブジェクトはチェックされません。
>
[cakephp Bookより](https://book.cakephp.org/3/ja/controllers/components/authentication.html)


注意

- versionは3.9.6です
- AuthComponentは4.0から非推奨です
- あくまでも流れなので詳しく知りたい方はソースコードを追ってみてください

コード

```php
  public function identify()
    {
        $this->_setDefaults();

        if (empty($this->_authenticateObjects)) {
            $this->constructAuthenticate();
        }
        foreach ($this->_authenticateObjects as $auth) {
            $result = $auth->authenticate(
                $this->getController()->getRequest(),
                $this->getController()->getResponse()
            );
            if (!empty($result)) {
                $this->_authenticationProvider = $auth;
                $event = $this->dispatchEvent('Auth.afterIdentify', [$result, $auth]);
                if ($event->getResult() !== null) {
                    return $event->getResult();
                }

                return $result;
            }
        }

        return false;
    }
```

まず3行目の

```php
  $this->_setDefaults();
```
これは認証方法やログイン時のアクションメソッド等で特に指定が無ければデフォルトの設定を適用します。(例えば認証方法のデフォルトはFormオブジェクトでの認証となります)

次に5~7行目

```php
if (empty($this->_authenticateObjects)) {
     $this->constructAuthenticate();
   }
```

ここで実際に認証に使うオブジェクトが_authenticateObjectsプロパティにセットされていなかった場合に認証オブジェクトを_authenticateObjectsにセットします。(_authenticateObjectsプロパティにはBaseAuthenticate抽象クラスを継承したインスタンスが入ります)


8行目

```php
foreach ($this->_authenticateObjects as $auth) {
```
認証オブジェクトが入ったarrayをループします(認証方法が複数存在する可能性もあるのでループ処理をして一個ずつ認証オブジェクトを試します)

9~12行目

```php
$result = $auth->authenticate(
                $this->getController()->getRequest(),
                $this->getController()->getResponse()
            );
```

ここで認証オブジェクトにリクエストとレスポンスのオブジェクトを渡し認証結果を受け取ります。


13~22行目

```php
if (!empty($result)) {
        $this->_authenticationProvider = $auth;
        $event = $this->dispatchEvent('Auth.afterIdentify', [$result, $auth]);
            if ($event->getResult() !== null) {
                return $event->getResult();
            }

        return $result;
```

そして認証が成功した場合にどの認証方法で認証されたのかを_authenticationProviderプロパティに認証に使ったオブジェクトを代入し、その後Auth.afterIdentifyイベントを発行し、リスナーがある場合はその結果を返し無い場合は認証オブジェクトから返された結果をそのまま返します。




```php
return false;
```

そして上記の処理で認証ができなかった場合はfalse, 認証失敗になります。


以上です。

なにか間違いや修正した方がいいことがあればご指摘をお願い致します。
【Railsチュートリアル】第7章 ユーザー登録②

#7.2 ユーザー登録フォーム
* ユーザー登録フォームを作成する。

##7.2.1 form_withを使用する
* Railsでform_withヘルパーメソッドを使う。

```ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])
  end

  def new
    #Userインスタンスを作成し、@userに代入せよ
    @user = User.new
  end
end
```

```ruby:app/views/users/new.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_with(model: @user, local: true) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
  </div>
</div>
```

### 演習 1
試しに、ブロックの変数fをすべてfoobarに置き換えてみて、結果が変わらないことを確認してみてください。確かに結果は変わりませんが、変数名をfoobarとするのはあまり良い変更ではなさそうですね。その理由について考えてみてください。

`f.label`の`f`は`form`を示しており、それを`foobar`にしてしまうと、意味がわからなくなってしまう。
また、`foobar`は意味の無い単語のためこの場合は適さない。

##7.2.2 フォームHTML

```ruby:app/views/users/new.html.erb
<%= form_with(model: @user, local: true) do |f| %>
  .
  .
  .
<% end %>
```

**XHR request** って？
> JavaScriptなどのウェブブラウザ搭載のスクリプト言語でサーバとのHTTP通信を行うための、組み込みオブジェクト（API）である。Google マップ、Facebookなどが利用している。
参考: [XMLHttpRequest - ウィキペディア（Wikipedia）](https://ja.wikipedia.org/wiki/XMLHttpRequest)

**API** って？
> Application Programming Interfaceの頭文字。
APIとはソフトウェアやアプリケーションなどの一部を外部に向けて公開することにより、第三者が開発したソフトウェアと機能を共有できるようにしてくれるもの。
参考: [データの時間](https://data.wingarc.com/what-is-api-16084)

```ruby:app/views/users/new.html.erb
<%= f.label :name %>
<%= f.text_field :name %>

# @userの属性を設定するために特別に設計されたHTMLを返す
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />
```

**ユーザーの作成で重要なこと**

* `input`ごとにある特殊な`name`属性
* `form`タグ自身

```ruby:app/views/users/new.html.erb
# /users（action="/users"）に対してHTTPのPOSTリクエスト（method="post"）を送信せよ
<form action="/users" class="new_user" id="new_user" method="post">
```

###演習 1
『Web基礎編: HTML』ではHTMLをすべて手動で書き起こしていますが、なぜformタグを使わなかったのでしょうか? 理由を考えてみてください。

formタグを使わなかった理由は『Web基礎編: HTML』において使う必要がなかったから？
formタグは入力・送信フォームを作成するために使われるので、この機能を実装しない『Web基礎編: HTML』では、そもそも必要がないので使わなかった？
（本文が有料のため確認できておりませんが）
よく使う演算子リスト




#算術演算子
記号 |	効果
-----|-----------------
+    |	加算
-    |	減算(マイナス符号）
*    |	乗算
/    |	除算
%    |	余り
**   |	累乗
.    |	文字列結合

#代入演算子
記号 |	効果
-----|-------------------
=    |	代入
+=   |	加算して代入
-=   |	減算して代入
*=   |	乗算して代入
/=   |	除算して代入
%=   |	乗余して代入
**=  |	累乗して代入
.=   |	文字列として結合(追加)

#比較演算子
記号 |	効果
-----|-------------------------
　== |	値が等しければtrue
　!= |	値が等しくなければtrue
　>  |	値が大きければtrue
　<  |	値が小さければtrue
　>= |	値が同じか大きければtrue
　<= |	値が同じが小さければtrue
　eq |	文字列として等しければtrue
　ne |	文字列として等しくなければture
　lt |	文字コードが大きければtrue
　gt |	文字コードが小さければtrue
　le |	文字コードが同じか大きければtrue
　ge |	文字コードが同じか小さければture
　cmp|	大きければ－1、等しければ0、小さければ1
　=~ |	正規表現。指定文字列があればtrue
　!~ |	正規表現。指定文字列がなければtrue
　!  |	否定。真のとき偽、偽のとき真
　<=>|	値が大きければ-1、等しければ0、小さければ1

     

#論理演算子

記号 |	効果
----|---------------------------------
　&& |	条件が両方成立すればtrue (AND)
 ｜｜|	どちらかの条件が成立すればtrue (OR)
&   |	ANDを返す
｜   |	ORを返す
^   |	XORを返す
(&,｜,^)=   |	指定論理を抽出して代入
ホストレベルのリダイレクトを行う（Rack層）

## はじめに

Rails でホストレベル（相対パスではなく、ドメイン名を含む絶対パスレベル）でのリダイレクトを行う場合、要件によっていくつかの実装パターンがあります。
今回はサイトリニューアルの関係でドメインが変わっており、Web アプリケーションはそのまま同じものを使用します。
また、 Rails で静的ファイルを提供する場合に使用する `public` ディレクトリも含めて他のドメインへリダイレクトしたかったので、  [Rack::HostRedirect](https://github.com/gbuesing/rack-host-redirect) を選択しました。
メジャーな他の方法はコントローラのコールバックや、routes.rbの定義で実装する方法だと思いますが、この二つでは `public` ディレクトリをリダイレクトできないため、rack 層からのリダイレクトを行うこの gem を選択しました。試していませんが、Apache の mod_rewrite ばりに多機能な　[Rack::Rewrite](https://github.com/jtrupiano/rack-rewrite) あたりでも同じことができると思います。

サイトリニューアルなどでドメイン名を変更する場合、SEOの観点では相対パスをそっくり維持しドメインのみ異なる 301 Moved Permanently なリダイレクトが必要になるため、このような実装をよく行います。

## 実装

実装というより単に定義で終わりですが、gem を入れた後はこんな感じになります。
[gem Config](https://github.com/rubyconfig/config) を使っているので、 `Setting.production_old_host` に旧ドメイン、 `Settings.production_host` に新ドメインを定義しています。

```ruby
# config/application.rb
    config.middleware.insert_before ActionDispatch::Static, Rack::HostRedirect, {
      [Settings.production_old_host] => Settings.production_host
    }
```

この gem のことを全く知らずにここだけ見ても、何をしているか分かりやすくて良いですね。

## 解説

キモなのは `config.middleware.insert_before ActionDispatch::Static` で、この定義がないと、この gem を使っても `public` ディレクトリをリダイレクトできません。

この定義が何をしているかは、Rails ガイドを読むのが一番良さそうです。
[Rails ガイド | 3 Action Dispatcherのミドルウェアスタック](https://railsguides.jp/rails_on_rack.html#action-dispatcher%E3%81%AE%E3%83%9F%E3%83%89%E3%83%AB%E3%82%A6%E3%82%A7%E3%82%A2%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF) 

ちゃんと理解するには Rack とは何か？ を知る必要があるのですが、Webアクセス（リクエストとレスポンス）を簡単に扱えるようにする仕組みを提供するミドルウェアといったところでしょうか。Rack はあくまで仕組みの名前で、それを実現する ミドルウェアは多数の gem で構成されています。うちの環境ではこんな感じ。

```
% rails middleware

use Rack::MiniProfiler
use Rack::Sendfile
use Rack::HostRedirect
use Rack::Cors
use ActionDispatch::Static
use ActionDispatch::Executor
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rack::Timeout
use ActionDispatch::RemoteIp
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use MetaRequest::Middlewares::Headers
use ActionDispatch::DebugExceptions
use BetterErrors::Middleware
use Rollbar::Middleware::Rails::RollbarMiddleware
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActionDispatch::Cookies
use ActionDispatch::Session::RedisStore
use ActionDispatch::Flash
use ActionDispatch::ContentSecurityPolicy::Middleware
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Rack::TempfileReaper
use Warden::Manager
use Bullet::Rack
use MetaRequest::Middlewares::MetaRequestHandler
use MetaRequest::Middlewares::AppRequestHandler
run Nurses::Application.routes
```

入れている gem によってこの内容は変化しますが、名前でなんとなく何をやっているのか分かるものも多いですね。この中の `ActionDispatch::Static` が、`public` ディレクトリで静的ファイルを提供している gem です。
この `ActionDispatch::Static` が先に呼び出されて実行されてしまうとリクエストを解釈してレスポンスを返すところまでやってしまうため、リダイレクト処理を挟む余地がなくなってしまいます。
そのため、`config.middleware.insert_before(existing_middleware, new_middleware, args)` を使用してこの gem の前に `Rack::HostRedirect` を呼び出す必要があるわけです。