OmniAICreator/Qiita-1.07M huggingface dataset:
カーネルが上がって起動しない場合の意外な盲点

# ubuntu recovering journal …で起動しない

- 検索すれば、例えば以下のような役に立つ記事が出てきます。

https://zenn.dev/rebi/scraps/80e12b333afca0

https://pc.watch.impress.co.jp/docs/column/ubuntu/1471435.html

古くは

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14159686589

- ただし、私の場合は前者に近い様です。

## そもそもGRUBメニューが開かないんです！！
- 何度ブート画面（マザーのPOST画面）でESCを押しても起動しない
- チャレンジする事1時間近く…ようやくGRUBメニュー登場

## GRUBメニューでAdvanced options for Ubuntuが選べない
- 下を押すと一気にUEFIのメニューを開くになり
- 上を押せば通常起動
- どうしても真ん中に止まらない。

# キーボードが悪かった！

**業務用に使っているキーボードが英字だけなのでゲーミングキーボード使ってた！**
- 普通のメーカ用PCのしょぼいキーボードにするとあら不思議
- 普通にカーネルの選択ができます。

:::note warn
なんとも情けない盲点・・・(-_-;)
- 応答速度が速すぎて飛びまくっていた模様
:::

:::note info
これが原因だった
カーネルが6.xxに上がっている・・・
::: 

- 別のPCもカーネルが上がって画面真っ暗だったんで、ここにあたりを付けます。

### Recovery modeではなく、今まで起動できたカーネルで起動

- Recovery mode でroot状態で Grubの設定を変えても普通に起動してきてしまいます・・・
- と、いうことで設定変更は起動できるバージョンで普通に行いましょう。

```Ubuntu:ターミナル

sudo vi /etc/default/grub


```

```Ubuntu:ターミナル

GRUB_DEFAULT=0

# こちらを現在使用中のカーネルに変更
# 保存後に
sudo update-grub

```

:::note info
エディタはお好みのものをお使いください
::: 

- 新しいのを使えと注意されるが、起動しないのは困るので、とりあえず無視。

@loach さんの記事

https://qiita.com/loach/items/53b9c84e47b4b65de8ea

こちらが非常に参考になると思います。

:::note info
Nvidia・・・といってもほとんどの方だと思いますが、
- ドライバ・CUDAの更新でも起動しなくなりますので、気を付けたいですね。
:::
コメントアウトしたコードが動作に影響する場面がある件について(マジックコメント)

# コメントアウトしたコードが動作に影響する場面がある

### 【背景】
Swiftの環境構築の際や、Rubyで文字列を変換する為に文字コードを指定することがあった。
そこで、
```ruby
# coding:UTF-8

# 以下各自のコードが続く
```
という記述があり、この
「```# coding:UTF-8```はコメントアウトされているから、書かなくてもいいよね」
と思ったのだが、そうはいかなかったことが発端ですと。

他にも、Swiftの環境構築で、SwiftPM（PackageManager）を導入する際、次の記述をファイルに書き込んだのだが、
1行目の
```// swift-tools-version: 5.8```
この記述が無いとビルドに失敗したりする。
```swift
// swift-tools-version: 5.8

import PackageDescription

let package = Package(
    name: "BuildTools",
    dependencies: [
        .package(url: "https://github.com/nicklockwood/SwiftFormat", exact: "0.51.11"),
        .package(url: "https://github.com/realm/SwiftLint", exact: "0.47.0")
    ],
    targets: [.target(name: "BuildTools", path: "")]
)
```



---

### 最後に
このように、コメントアウトされながらも意味を持つコードがあるということを知らなければ、エラーの原因を探る際にかなり遠回りをすることになるので、知っておくと良いかもね。
neosでlogix その143

# 概要
neosでlogixやってみる。
練習問題、やってみた。

# 練習問題
外部画像を表示せよ。

# 方針
外部画像を取得してマテリアルにして、クアドメッシュにレンダリングする。

# 実行結果

![2023-08-06 22.50.59.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a368ae2b-9ee1-0bff-fba6-b30cef10985b.jpeg)


# 俺コード

```
FrooxEngine.StaticTexture2D.url = "https://apod.nasa.gov/apod/image/2308/GianniTumino_Moon_Rays_JPG_LOGO_1024pix.jpg"
FrooxEngine.UnlitMaterial.Texture = FrooxEngine.StaticTexture2D.id
FrooxEngine.MeshRenderer.Materials = FrooxEngine.UnlitMaterial.id
FrooxEngine.MeshRenderer.Mesh = FrooxEngine.QuadMesh.id

```

# 手順で説明
- devツールを装着する。
- 新規＞空のオブジェクトを作る。
- コンポーネントをアタッチする。
Assets -> Materials -> UnlitMaterial
Assets -> Procedual Meshes -> QuadMesh
Assets -> StaticTexture2D
Renderering -> MeshRenderer
- 設定する。
StaticTexture2Dのurlは "https://apod.nasa.gov/apod/image/2308/GianniTumino_Moon_Rays_JPG_LOGO_1024pix.jpg"
UnlitMaterialのTextureはStaticTexture2D
MeshRendererのMaterialsはUnlitMaterial
MeshRendererのMeshはQuadMesh

以上。
GitlabのIssueについてansibleで目的のIssueに絞って外部出力してみた

## 背景
Gitlabで管理しているIssueについて特定の条件を満たすIssueだけを取得したいと思い、
実装してみたため、備忘録的にまとめておきます。

## 利用したもの
- Ansible
- GitLab

### プログラム
汎用的なソースコードを以下に記載します。

- GitLabからIssueを取得する基本的なplaybook
```yml:main.yml
---
- name: Notification of　GitLab Issue
  hosts: localhost
  vars:
    gitlab_api_token: "GitLabのAPIトークン"
    gitlab_project_id: "GitLabのIssue作成先プロジェクトID"
    gitlab_server: "GitLabサーバIPアドレス"
    per_page : 1000　#Issue取得の上限

  tasks:
    - name: Get GitLab Issue
      block:
        - name: Issueを取得
          uri:
            url: "https://{{ gitlab_server }}/api/v4/projects/{{ gitlab_project_id }}/issues?" #Issueを絞るときにはこのurlの記述を工夫する
            method: GET
            headers:
              PRIVATE-TOKEN: "{{ gitlab_api_token }}"
            status_code: 200
            validate_certs: no
          register: pickup_issues

        - name: Parse GitLab Issues
          set_fact:
            issue_count: "{{ pickup_issues.json | length }}"
            issues: "{{ pickup_issues.json }}"
          when: pickup_issues.status == 200

        - name: Create output Message
          set_fact:
            issues_table: |
              {% for issue in issues %}
              {{ "---------------------------------------------------------------------------------------------" }}
              {{ "[作成日時]:" + issue.created_at | regex_replace('T.*', '') }}
              {{ "[タイトル]" + issue.title }} 
              {{ "[リンク]" + issue.web_url }} 
              {% endfor %}


```

- 対象を絞るときには上記ソースコードのurlを以下のような記述にすることで対象を絞ることが可能です

  - 特定の期間に作成されたIssue
    期間の始まり：start_date: "2023-06-01"
    期間の終わり：end_date_detail: "2023-06-30"
    ```
    url: "https://{{ gitlab_server }}/api/v4/projects/{{ gitlab_project_id }}/issues?created_after={{ start_date }}&created_before={{ end_date }}&per_page={{ per_page }}"
    ```

  - OPENされているIssue
    ```
    url: "https://{{ gitlab_server }}/api/v4/projects/{{ gitlab_project_id }}/issues?state=opened&per_page={{ per_page }}"
    ```

  - lableがついていないIssue
    ```
    url: "https://{{ gitlab_server }}/api/v4/projects/{{ gitlab_project_id }}/issues?labels=none&per_page={{ per_page }}"
    ```

本件について躓いた点としては、明らかに20を超える対象Issueが存在する場合に、なぜか出力されるIssueの数が20を上限にそれ以上表示されない現象が発生したため、調査したところgitLabのデフォルトの1ページあたりのIssue表示数のデフォルトが20であり、これに起因していたことがわかりました。
これを是正するために以下ポイントに注意が必要です。

:::note warn
urlにてパラメータper_pageを想定されるIssueの出力よりある程度大きな値で指定しておく
:::


## 終わりに
前回はgitLabのIssue作成について記事を記載しましたが、今回は記事の抽出について実施してみました。
抽出したIssueについて出力だけでなく処理を記述すれば、統計なども自動的に実施できるので、今後も応用して色々やってみようと思います。
VSCodeでC#の補完が効かなくなった時の対処法(2023年8月)

# はじめに
2023年8月初頭、VSCodeでC#の補完(IntelliSense)が効かなくなりました。
筆者を含め、VSCodeでUnity開発をしている結構な人がハマったらしいので修正方法を記事に残しておきます。

# 修正方法
**VSCodeのC#の拡張機能(Microsoft公式が出している物)をv2.x.x以上にアップデートしないでください。**

と言っても、自動でアップデートされる場合が多いと思います。
もしアップデートしてしまったら、別のバージョン(v1.26.0)をインストールしてください。
アンインストールの横から可能です。
![スクリーンショット 2023-08-07 12.05.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318712/d7df4074-9572-b333-80cf-0d63cdb1a24e.png)

# 補足：筆者がやった行動一覧
今回は特に効果がありませんでしたが将来的に役立つかもしれないので一応、これも書いておきます。

- PC再起動
- VSCode再インストール
- .NETの更新
- .NETの設定の変更
SPSS Modeler自動分類、自動数値、自動クラスタリングでモデリングパラメーターを指定する

SPSS Modeler自動分類、自動数値、自動クラスタリングの各ノードでは自動的にいろいろなアルゴリズムのモデルが作れて便利です。

しかしながら、同じアルゴリズム内で様々なパラメータを試したいこともあります。

その場合モデルパラメーターを指定することができます。

例えば、自動数値ノードで線形回帰の変数選択の異なるモデルを作ってみます。

* テスト環境
    * Modeler 18.4
    * Windows 11 64bit
    
#### サンプルストリーム
https://github.com/hkwd/spsssample/raw/master/230807%E8%87%AA%E5%8B%95%E6%95%B0%E5%80%A4/230807%E8%87%AA%E5%8B%95%E6%95%B0%E5%80%A4.str

#### 利用データ
右クリックでリンク先を保存してください。

https://raw.githubusercontent.com/hkwd/spsssample/master/230807%E8%87%AA%E5%8B%95%E6%95%B0%E5%80%A4/sales2021full.csv

# 設定方法

「エキスパート」タブを開き、「線形回帰」のモデルの「モデルパラメータ」から「指定...」を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/9f469778-af61-8a7b-33e2-2b791f970511.png)

「シンプルタブ」の「方法」の「オプション」で「指定...」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/d3c86eee-bcf5-bdea-7cbb-e03552b52048.png)

以下のように3つのオプションを選んでみます。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/928f9ae1-ca75-21f1-e15e-78aafcb626f4.png)

「OK」で閉じます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/75c50183-c07f-14cd-c077-adf80c70837b.png)

すると、「線形回帰」のモデル数が「3」になっています。つまり三パターンのモデルを作ることを意味しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/7f319956-1915-477f-1114-22dae8e0919f.png)

さらに今度は他のオプションも選択してみます。
「モデルパラメータ」から「指定...」を開き、「エキスパート」タブの中の「投入」から「指定...」を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/efd3cb2a-65b9-abec-f661-2f32408b5436.png)

以下のようにデフォルトの「0.05」のほかに「0.1」を指定してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/11e903da-35ee-9bc2-21d6-8834eb9dae1c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/c789c35e-fb39-580a-f6f7-ef23610edc9c.png)

するとモデル数が「6」になっています。「方法」で3パターン＊「投入」で2パターンで合計6個のモデルが作成されることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/57070e47-78e9-11e1-df54-633be88f8640.png)


「モデル」タブで「使用モデル数」を「６」にして作成してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/83dd5c69-04d2-2114-eb81-f8143be7c516.png)


6つのモデルができました。一番上のモデルをダブルクリックしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/8c679681-de1a-dc1f-5e60-4187bb70df3a.png)

このモデルは「方法」は「ステップワイズ法」、「投入」で「0.05」のオプションで作られたモデルであることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/8c6ce978-e43d-ddfc-b418-2f60f3484609.png)



# 参考

#### SPSS Modeler ノードリファレンス 5-11 自動分類(Autoモデリング)
https://qiita.com/416nishimaki/items/3861d67b960a91fa4137
#### SPSS Modeler ノードリファレンス 5-12 自動数値(Autoモデリング)
https://qiita.com/416nishimaki/items/2fb9f3a439afba803691
#### ノードのヘルプ　自動クラスタリング・ノード
https://www.ibm.com/docs/ja/spss-modeler/18.4.0?topic=nodes-auto-cluster-node
ROSプログラムをショートカットアイコンから実行する

- 手順１: 設定ファイルの作製

`~/デスクトップ`内に以下のような設定ファイルを作製

```bash:aaa.desktop
[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Exec=/home/dev/デスクトップ/run.sh
Name=アプリ1
Comment=Test Application
Icon=/home/dev/デスクトップ/aaa.png
```

※ ファイル書き換え： デスクトップから設定ファイル右クリックメニューのProperies > Permission から書き込み権限を `Read and Write` にする必要がある
※ ショートカットアイコン化： Properies > Permission から書き込み権限を `Read Only` に必要がある + デスクトップから設定ファイル右クリックメニュー`Allow launching`をONにする必要あり
※`Allow launching`が見つからない場合　確認事項
    1. Exec内の実行ファイルが存在するか
    2. 実行ファイルに実行権限が付与されているか(`chmod +x run.sh`)
  



- 手順２：実行ファイルの作製

```bash:run.sh
gnome-terminal -- bash -c "source /opt/ros/noetic/setup.bash;cd /home/dev/{ワークスペース名};python3 aaa.py;exec bash"
```

※ `ポイント１`：実行ファイルで`source /opt/ros/noetic/setup.bash`のように環境設定をする必要あり
※ `ポイント２`：また、`gnome-terminal`でターミナルを立ち上げて実行するとでエラーが見えてデバッグしやすい
ts-mocha + typescript 環境では期待値どおりにテストを実行できない

# 環境

* typescript : 5.1.6
* ts-mocha : 10.2.0
* ts-node : 10.0.0
* tsconfig-paths: 4.2.0

# 期待値(何がしたいのか)

* `mocha + chai` 環境で`typescript`で書かれたコードのテストがしたい
* `tsconfig`に割当している`paths`もテストコード内で認識してほしい

# 事象（実際はどうなるか）

`ts-mocha`等、`ts-node`に依存しているpackageを実行すると、以下のエラーになる。

```bash:bash
# tsconfig paths を認識させる場合
> ts-mocha --paths -p ./tsconfig.json

[ERROR] The "path" argument must be of type string. Received an instance of Array
```

```bash:bash
# tsconfig paths は無視する場合
> ts-mocha -p ./tsconfig.json

✖ ERROR: TypeError: value.replace is not a function
# ( ...以下略... )
```

# 結論（解決策）

一旦`tsc --showConfig`で、`tsc`が実際に読み込んでいる`tsconfig`を出力してから、その出力された`tsconfig`を参照するように指定する

```bash:bash
# tsconfig.tsnode.json を一旦出力
$ tsc --project=./tsconfig.json --showConfig > tsconfig.tsnode.json

# 出力した tsconfig.tsnode.json を使う
# tsconfig paths を認識させる場合
$ ts-mocha --paths --project=./tsconfig.tsnode.json
```

```bash:bash
# tsconfig.tsnode.json を一旦出力
$ tsc --project=./tsconfig.json --showConfig > tsconfig.tsnode.json

# 出力した tsconfig.tsnode.json を使う
# tsconfig paths は無視する場合
$ ts-mocha --project=./tsconfig.tsnode.json
```

### npm script の設定例

```jsonc:package.json
{
  "script":{
    "pretest":"tsc -p ./tsconfig.json --showConfig > tsconfig.tsnode.json",
    "test":"ts-mocha --paths -p ./tsconfig.tsnode.json"
  }
}
```

```bash:bash
# テストコマンドを実行するだけで済む
npm run test
```

# 参考

https://github.com/TypeStrong/ts-node/issues/2000#issuecomment-1519339593
羊による羊のためのJavaScript復習②変数

# 1.変数(Variable)<br>
## 変数(Variable)とは
値を格納するために名前付けされた場所
メモリの確保
これにより、あらかじめ決めておいた名前を使って、予測できない値にアクセスできる
  
  cf.
・[変数_(プログラミング) (Wikipedia)](https://ja.wikipedia.org/wiki/変数_(プログラミング))
・[JavaScript の変数宣言](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Grammar_and_types#declarations)
・[JavaScript の var 文](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/var)

## 関数宣言<br>
`let 変数名 = 代入値;`：再代入可能
`const 変数名 = 代入値;`：再代入不可

## 書き方 ・ 使い方<br>

`let 変数名 = 代入値;`
`const 変数名 = 代入値;`


1.

```
let sum=1+2+3+4+5;

console.log(sum * 5);
console.log(sum / 2); 
```
letを用いてsumという変数を定義する、その代入値は1 + 2 + 3 + 4 + 5
console.log()で変数sumに算術をした結果をconsoleに表示させる

result:
```
75
7.5
```

2.
```
let today = "3月28日";
let text = "今日は" + today + "です。";
let isSunday = false;
console.log(today, text, isSunday);
```
letで変数todeyを"3月28日"と代入して定義する。<br>
letでtextを"今日は" + today + "です。"と代入して定義する、ここでtodayは"3月28日"
letで変数isSundeyをfalseと代入して定義する
console.log()でtoday, text, isSundayの値をそれぞれ出力する
result:
```
3月28日 今日は3月28日です。 false
```

# 2.代入<br>
メモリへの書き込み<br>
右辺を左辺に保存するイメージ、代入演算子`=`を用いる<br>

# 3.再代入<br>
一度確保したメモリにもう一度値をセットする<br>

```
let number = 2;
number = number + 1;
number;　// => ?
```

letで変数numberに2を代入してnumberを定義する。<br>
numberにnumber(ここでは2) + 1と再代入する。<br>
出力するnumberの値は3

result:
```
3
```
# 4.変数まとめ<br>
| 用語 | 意味 |
|:--|:--|
| 変数(Variable) | メモリの確保 |
| 代入(Assignment) | メモリへの書き込み |
| 再定義(Redeclaration) | メモリの確保のし直し |
| 再代入(Reassignment) | 一度確保したメモリにもう一度値をセットする | （）
ChatGPTをFine-tuningして独自情報を回答させる

# 環境準備
```zsh
% pip3 install --upgrade openai
% export OPENAI_API_KEY="sk-xxxxxxx"

// missing `pandas` のエラーが出たため
% pip3 install openai"[datalib]"
```

# 学習データの準備
CSV形式で理想の質問と答えのペアを作る。
```sakai01.csv
prompt,completion
境町の自動運転バスARMAについて教えて。,境町では、ソフトバンク株式会社の子会社であるBOLDLY株式会社及び株式会社マクニカの協力のもと、自動運転バスを3台導入し、生活路線バスとして定時・定路線での運行を令和2年11月26日（木）から開始しました。なお、自治体が自動運転バスを公道で定常運行するのは、国内で初めてです。
運行時間は？,午前7時40分〜午後4時まで。土日祝日も運行。
乗車料金は？,無料です。
乗車定員は？,8名です。
```
openaiのコマンドツールで、csvからJSONLファイルに変換するツールが用意されていた。

```zsh
% openai tools fine_tunes.prepare_data -f sakai01.csv
```

```json:sakai01_prepared.jsonl
{"prompt":"境町の自動運転バスarmaについて教えて。 ->","completion":" 境町では、ソフトバンク株式会社の子会社であるBOLDLY株式会社及び株式会社マクニカの協力のもと、自動運転バスを3台導入し、生活路線バスとして定時・定路線での運行を令和2年11月26日（木）から開始しました。なお、自治体が自動運転バスを公道で定常運行するのは、国内で初めてです。 END"}
{"prompt":"運行時間は？ ->","completion":" 午前7時40分〜午後4時まで。土日祝日も運行。 END"}
{"prompt":"乗車料金は？ ->","completion":" 無料です。 END"}
{"prompt":"乗車定員は？ ->","completion":" 8名です。 END"}
```

# Fine-tuningの実行
```zsh
% openai api fine_tunes.create -t sakai01_prepared.jsonl -m text-davinci-003
Error: Invalid base model: text-davinci-003 (model must be one of ada, babbage, curie, davinci) or a fine-tuned model created by your organization: org-xxxxx (HTTP status code: 400)
```
モデル指定が「GPT3.5」だとだめっぽい。davinciを指定してみる。
https://platform.openai.com/docs/models/overview

```zsh
% openai api fine_tunes.create -t sakai01_prepared.jsonl -m davinci         
Upload progress: 100%|███████████████████████████████████████████████████████████| 5.14k/5.14k [00:00<00:00, 2.55Mit/s]
Uploaded file from sakai01_prepared.jsonl: file-xxxxxxxxxxxx
Created fine-tune: ft-xxxxxxxxxxxx
Streaming events until fine-tuning is complete...

(Ctrl-C will interrupt the stream, but not cancel the fine-tune)
[2023-08-04 22:19:24] Created fine-tune: ft-xxxxxxxxxxxx

Stream interrupted (client disconnected).
To resume the stream, run:

  openai api fine_tunes.follow -i ft-xxxxxxxxxxxx
```
中断したりするので、再開させる。
```zsh
% openai api fine_tunes.follow -i ft-xxxxxxxxxxxx
[2023-08-04 22:19:24] Created fine-tune: ft-xxxxxxxxxxxx
[2023-08-05 00:29:34] Fine-tune costs $0.26
[2023-08-05 00:29:34] Fine-tune enqueued. Queue number: 1
[2023-08-05 00:40:42] Fine-tune started
[2023-08-05 00:43:52] Completed epoch 1/4
[2023-08-05 00:43:59] Completed epoch 2/4
[2023-08-05 00:44:07] Completed epoch 3/4
[2023-08-05 00:44:15] Completed epoch 4/4
[2023-08-05 00:44:48] Uploaded model: davinci:ft-boldly-2023-08-04-15-44-48
[2023-08-05 00:44:49] Uploaded result file: file-xxxxxxxxxxxx
[2023-08-05 00:44:50] Fine-tune succeeded

Job complete! Status: succeeded 🎉
Try out your fine-tuned model:

openai api completions.create -m davinci:ft-boldly-2023-08-04-15-44-48 -p <YOUR_PROMPT>
```
完了！

# 結果の確認
```zsh
% openai api completions.create -m davinci:ft-boldly-2023-08-04-15-44-48 -p "自動運転バスの運行時間は？"
運行時間は？ 通常運行は午前7%
```
データ量が少ないからか、こちらが想定しているような回答は返ってこない。。


# 参考
https://dev.classmethod.jp/articles/888c355f2c88e117d172ec1bd3d28a435ee438766630638e3e9f7887aef8f5ee/
ChatGPTで英語学習を効率化　～英単語の意味を調べる～

# はじめに
毎日のように英単語の意味を調べますが、何度も同じことを検索していると気づくことがあります（少しでも効率的に単語を覚えたい…）。
そこで今回は、ChatGPTを利用して、英単語の意味を簡潔かつ効率的に出力する方法を紹介します。

# プロンプト作成
以下の機能があれば便利だと思い、プロンプトを作成しました。

・調べた単語の意味、使用例を表示させたい
・英単語のみの入力で認識させたい
・調べた単語をあとで復習できるように、過去に検索した単語を一覧表示させたい

```
ここでは英単語や熟語の意味を質問します。
以下のルールに従ってください。

- 単語や熟語のみが入力される。
- 「リスト作成」と入力された場合、過去に質問したすべての単語とその意味（日本語）のリストを出力。

出力項目
- 入力された単語。
- 日本語でその単語の意味。
- 入力された単語の使用例（例文）。
```

![プロンプト作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3471773/15c851fb-4083-e45d-6e21-7003326442b9.png)


# 実際に英単語の意味を聞いてみる
英単語・熟語のみの入力で、想定通りの内容を出力してくれました。

![英単語検索.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3471773/26f2efb4-68c8-6f78-d817-fe93ed095740.png)



# 調べた英単語をリストで表示
「リスト作成」と入力し、過去に検索した英単語リストを表示させます。
調べた単語をまとめて復習するのに便利だと思っています。

![英単語リスト作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3471773/b4b9b965-c566-eb7f-9ff8-3d186f0c4c40.png)


# 音声入力と組み合わせて
英単語を調べるケースでは短くシンプルな入力ですが、音声入力・出力と組み合わせることで「話す」、「聞く」というトレーニングも取り入れることができます。

https://chrome.google.com/webstore/detail/voice-control-for-chatgpt/eollffkcakegifhacjnlnegohfdlidhn?hl=ja


# まとめ
ChatGPTを用いて、「英単語の意味を調べる」作業を便利に、効率的に単語を覚えられるような方法を試してみました。
自分の理想とする出力にするには、プロンプトの工夫が必要だと感じました。

英英辞典のように英語で意味を出力する、類語も一緒に確認したいなど、出力項目を必要に応じて変えることで、「自分だけの単語辞書」としてChatGPTを利用することもできそうです。
[Rails] rbenv環境下でのERB Formatter/Beautifyのパスの設定

# 1. はじめに
`.html.erb`ファイルのフォーマッタとして有名なERB Formatter/Beautifyであるが、初期設定のままだと次の写真のように
![Screenshot 2023-08-07 at 11.06.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1694793/4f829637-7a06-55fb-c289-0a672450e314.png)
```
Couldn't run htmlbeautifier 'spawn htmlbeautifier ENOENT'
```
や
```
Error occurred while formatting: spawn htmlbeautifier ENOENT
```
というエラーが出てきてフォーマッタが動かなかった。

# 2. 対処法
```shell
$ rbenv which htmlbeautifier
```
を実行して返ってきたパスをSettingsのExecute Pathに指定する。

例：
GUIなら
![Screenshot 2023-08-07 at 11.10.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1694793/a36009b7-f660-a17d-27c6-4ac393890c16.png)
JSONなら
![Screenshot 2023-08-07 at 11.10.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1694793/6cec1779-da4d-1db0-8d37-87902f9fdb71.png)

# 3. 注意点
対処法を検索していると、
```shell
$ which htmlbeautifier
```
を実行すればいいというトラブルシューティングが見つかるが、rbenv環境下では`rbenv which`を使う必要があるようで、私の環境だと`which htmlbeautifier`を実行すると`htmlbeantifier not found`と言われてしまった。

# 4. 終わりに
rbenv下では`which`ではなく`rbenv which`を使うという、おそらく初歩的なところで躓いて時間を費やしてしまった。エラーメッセージで検索してもこの解決策に辿り着けなかったため、メモとして残しておきます。

Railsの勉強を始めたばかりの初心者なので、間違ったことを書いていたら指摘していただけると助かります。

# 5. 参考
- [rbenv cheatsheet](https://devhints.io/rbenv)
- [can't find htmlbeautifier MACOS · Issue #13 · aliariff/vscode-erb-beautify](https://github.com/aliariff/vscode-erb-beautify/issues/13)
scriptタグに指定するnonceについて

ある日、開発で使用しているgemのlayoutファイルに以下のようなコードを見かけました。

```erb:
<%= javascript_tag nonce: true do %>
```

`javascript_tag`に`nonce: true`のオプションが渡されています。
「なんぞこれ？」となったのでとりあえずnonceに関して調べてみました。

## nonceについて
scriptタグに付与することができるnonce属性は、XSS攻撃などで不正なスクリプトが実行されることを防ぐために利用されます。

nonceは"number used once"の略で、一度だけ使用される数値を意味しています。
scriptタグに設定されたnonce属性には以下のような使い捨ての乱数を設定し、ページを読み込むたびに異なる乱数が再設定されるようにします。

```html
<script nonce="8IBTHwOdqNKAWeKl7plt8g==">
  // …
</script>
```

さらに、nonceに設定した乱数と同じ値を`Content-Security-Policy`ヘッダーで送信するようにします。
そうすることで`Content-Security-Policy`ヘッダーに設定されたnonce値が設定されたscriptのみを実行対象とし、正規のnonce値を持たないscriptは実行されなくなります。

```
Content-Security-Policy: script-src 'nonce-8IBTHwOdqNKAWeKl7plt8g=='
```

https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/nonce

## Railsでnonceを使う
Railsでnonceを利用したい場合は以下の設定を`config/initializers/content_security_policy.rb`に記載します。

```ruby:config/initializers/content_security_policy.rb
Rails.application.config.content_security_policy do |policy|
  policy.script_src :self, :https
end

Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
```

これで以下のように`javascript_tag`に`nonce: ture`を渡せばnonce値が自動的に追加され、実行されるスクリプトを制限することができるようになります。

```erb:
<%= javascript_tag nonce: true do -%>
  alert('Hello, World!');
<% end -%>
```

ちなみに以下のメソッドでnonceに設定されている乱数を取得することもできます。

```ruby
request.content_security_policy_nonce
=> "3xdpMsDFBsRpwY8KQp//LQ=="
```

https://railsguides.jp/security.html#nonce%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B
野球部にオブジェクト指向プログラミングを説明したい

おはようございます！
今日からはオブジェクト指向プログラミングについて説明します！
ただ、まだ私自身の理解が正確ではないところが多いので、今日から3回か4回に分けて説明していきたいと思います！

初回の今日は「オブジェクトとは？」というテーマの記事を書いていきます。

オブジェクトとは一言で言うと
「プロパティとメソッドから構成される、現実世界の物体や概念をコード内で表す構造」
です。

この記事を読み終わった時にオブジェクト･プロパティ･メソッドという３つの言葉の意味が分かるということを目指します！
### パワプロで考える「オブジェクト」「プロパティ」「メソッド」

まずは、この３つの言葉の意味を説明します。
-　**オブジェクト**:　その「もの」の特性（プロパティ）と振る舞い（メソッド）を一つにまとめたものです。
-　**プロパティ**: オブジェクトの特性や属性を表します。
-　**メソッド**: オブジェクトの動作を表します。

これらをパワプロに当てはめて考えていきましょう。
パワプロではそのゲーム内で使える選手に対して、パラメータが振られていますよね。
例えばイチロー選手は、パワーがBでそれ以外は全てAだったと記憶しています。

これを「イチローオブジェクト」と考えてみると、
「プロパティ」は"選手名、ミート、パワー、走力、肩力、守備力"にあたり、
「メソッド」は実際にゲームで使った時の能力にあたります。
例えば、ミートカーソルの大きさはミートの値によって変化したり、打った時の打球の強さがパワーの値によって変化するといったことです。

これをコードで書くとこんな感じになります。
```JavaScript
// イチローオブジェクトを定義
const イチロー = {
    // 以下がプロパティ
    ミート : 7;,
    パワー : 120;,
    走力 : 14;,
    肩力 : 15;,
    守備力　: 15;,
　　　　　　　　// 以下がメソッド
    バッティング : function() {
        ミートカーソルの大きさが${this.ミート}で、打球の強さは${this.パワー}に比例する。;
    },
    守備　: function() {
        ${走力}の速さで操作できて、投げる強さは${肩力}に比例して、エラーするかどうかは${守備力}に比例する;
    },
};
```
イチロー選手の能力値が「プロパティ」にあたり、それによってゲーム内の動きがどのように変わるのかという処理が「メソッド」にあたります。そして、これらを合わせたものが「オブジェクト」になります。

なんとなくイメージは掴めたでしょうか？

### 他の例も見てみる
他にも野球に関連するオブジェクトを考えてみました。
1. プレイヤーオブジェクト
プロパティ:名前、ポジション（ピッチャー、キャッチャーなど）、打率、守備率
メソッド:投げる、打つ、守る
2. チームオブジェクト
プロパティ:チーム名、所属リーグ、勝敗記録、メンバー（プレイヤーオブジェクトのリスト）
メソッド:試合をする、練習をする、メンバーを追加する
3. 試合オブジェクト
プロパティ:ホームチーム、アウェイチーム、スコア、試合日、天気
メソッド:試合を開始する、スコアを更新する、試合を終了する

こう考えると、あらゆることをオブジェクトとして捉えることができそうですよね！

### 実際のコードを見てみる
それでは、実際のコードを見てみましょう。このコードは、人物を表すオブジェクトを作成しています。

```javascript
const person = {
  name: ["Mannami", "Nomura"],
  age: 23,
  bio: function () {
    console.log(`${this.name[0]} ${this.name[1]} is ${this.age} years old.`);
  },
  introduceSelf: function () {
    console.log(`Hi! I'm ${this.name[0]}.`);
  },
};
```

このコードでは、`name`や`age`などのプロパティと、`bio`や`introduceSelf`などのメソッドが定義されています。
先ほど説明した通り、プロパティは、オブジェクトの特徴を表し、メソッドは、オブジェクトができる動作を表します。
このコードは名前や年齢などの情報と、自己紹介する動作などが一緒になっています。

オブジェクト指向プログラミングでは、このように現実世界のオブジェクトを模倣してプログラムを構造化します。
パワプロで各選手の名前や能力が設定されているように、プログラムでも人物や物の特徴と動作を一緒にしたオブジェクトを作ります。

この概念を理解すると、プログラミングがより直感的になり、現実世界の問題を効率的に解決できるようになる、、そうです、、！。

### まとめ
今回のブログで学んだ要点を3つにまとめます。
1. **オブジェクト**: 野球のプレイヤーやチームのように、特徴と動作を一緒にしたもの。プログラミングでも、人物や物の特徴と動作を一緒にしたオブジェクトを作ります。
2. **プロパティ**: オブジェクトの特徴。名前や年齢など。これらの特徴は、オブジェクトが何であるかを定義します。
3. **メソッド**: オブジェクトの動作。バットで打つ、キャッチするなど。これらの動作は、オブジェクトが何をするかを定義します。

オブジェクト指向プログラミングは、プログラミングの中でも特に重要な概念だと昨日学習したサイトに書いてありました。
この記事を通して理解を深めるきっかけになれば嬉しいです。明日以降もオブジェクト指向プログラミングシリーズとして、記事を更新していきます。この記事がもしも役立ったらいいねやフォローをお願いします！

それでは今日も学習をスタートします！
Go言語で昔懐かしのPongを作ってみた話 - スタート画面、反射処理、フィールドの追加

前回の記事ではゴール判定と得点表示を追加しました。
今回はそのコードにスタート画面、反射処理、フィールドのを追加したので記載します。

## 動作デモ

以下は、アップデートされたPongの動作です。
![pong.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143932/1a72a8ef-3027-4053-547a-7511eb4104e9.gif)

## 追加・変更点

1. **スタート画面の追加**:
    ゲームが開始されていない状態でのスタート画面を追加しました。
プレイヤーはEnterキーを押すことでゲームを開始できます。
   
2. **ボールの反射処理の追加**:
    ボールが壁やパドルに衝突したときの反射処理を追加しました。

3. **フィールドの追加**:
    ゲームの中央にフィールド（線）を追加しました。


## 1. スタート画面の追加

ゲームの状態を管理する`GameState`型を定義し、`Starting`状態を追加してゲームが開始されていないときの振る舞いを制御します。

```go
type GameState int

const (
	Starting  GameState = iota // ゲームが開始されていない状態
	Playing                    // ゲームが進行中の状態
	Resetting                  // ボールがゴールした後、リセット中の状態
)
```

ゲームのデータを管理する`Game`構造体に、スタート画面に関する変数を追加します。

```go
type Game struct {
	state            GameState // ゲームの現在の状態
	textBlinkTicker  int       // スタートメッセージの点滅用タイマー
	showStartMessage bool      // スタートメッセージを表示するかのフラグ
}
```

ゲームのロジックを更新する`Update`メソッドに、ゲームが`Starting`状態のときの処理を追加します。この処理では、スタートメッセージが点滅し、プレイヤーがEnterキーを押すとゲームが開始されます。

```go
case Starting:
	// ゲーム開始前の処理
	g.textBlinkTicker++
	if g.textBlinkTicker >= 30 {
		// スタートメッセージの点滅を切り替え
		g.showStartMessage = !g.showStartMessage
		g.textBlinkTicker = 0
	}
	if ebiten.IsKeyPressed(ebiten.KeyEnter) {
		// Enterキーが押されたらゲームを開始
		g.state = Playing
		g.ballPositionX = screenWidth / 2
		g.ballPositionY = screenHeight / 2
	}
```

## 2. ボールの反射処理の追加

ボールが壁やパドルに衝突したときに、ボールが反射する処理を追加します。

```go
// ボールが左の壁に触れた場合の処理
if g.ballPositionX < 0 {
	g.ballDX = -g.ballDX
	g.ballPositionX = 0
	g.player2Score++
	g.state = Resetting
} else if g.ballPositionX > screenWidth-ballSize {
	// ボールが右の壁に触れた場合の処理
	g.ballDX = -g.ballDX
	g.ballPositionX = screenWidth - ballSize
	g.player1Score++
	g.state = Resetting
}

// ボールが上または下の壁に触れた場合の処理
if g.ballPositionY < 0 {
	g.ballDY = -g.ballDY
	g.ballPositionY = 0
} else if g.ballPositionY > screenHeight-ballSize {
	g.ballDY = -g.ballDY
	g.ballPositionY = screenHeight - ballSize
}
```

## 3. フィールドの追加

ゲームの中央にフィールド（線）を追加しました。

```go
// 画面の中央に縦線を描画
for i := 0; i < screenHeight; i += 30 {
    ebitenutil.DrawRect(screen, screenWidth/2-1, float64(i), 2, 20, color.White)
}
```

## まとめ

これらの変更により、Pongに近づいてきて楽しくなってきました。
ここからも小さな箇所でもアップデートを続けていこうと思います。

## 前回
https://qiita.com/benjamin1gou/items/3e4e18bae9ccfa57e634
Irisでクリップボードにテキストをコピーする方法

# 目次
1. はじめに
1. 完成イメージ
1. 実装方法
1. まとめ


# はじめに
ボタンをタップした時にクリップボードにテキストをコピーさせたい時はありませんか？
IrisではクリップボードにテキストをコピーするためのAPIは用意されていません。
ですが、NFIを追加することでクリップボードコピーの機能を実装することができます。

意外と簡単なのでチェックしてみてください！
# 完成イメージ
今回は下記のように、
ボタンを押すとテキストボックスに入力した文字をクリップボードにコピーする機能を実装していきます！
![ezgif-3-50b9b0bcb4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/e6a470eb-04c4-4753-0bb5-fb53314b2036.gif)


# 実装方法
早速実装方法について紹介します。

## Form作成
まずは、テキストボックスに入力した文字をクリップボードにコピーしたいため、
テキストボックスとコピーを実行するボタンを配置したフォームを作成します。
![スクリーンショット 0005-08-07 10.57.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/e9e6f67b-2a0d-1524-4f8b-8f75f028a53d.png)


## NFI追加
Androidの場合のみ、  
IrisメニューのEdit->Manage Native Function APIをクリックし、下記の3つを追加します。
・android.content			
・android.text			
・com.android.server.clipboard		

![スクリーンショット 0005-08-07 11.37.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/6ad8001c-7aee-bc26-b15a-c75827ce0a75.png)
このようになればOKです。	
![スクリーンショット 0005-08-07 10.29.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/337d70aa-672c-4129-f7ed-35b8855dee61.png)


## ロジック作成
次に、ボタンを押すとテキストボックスに入力した文字を
クリップボードにコピーするロジックをControllerに追加していきます。

```frmProfile.js
  onClickCopy : function(){
    let self = this;
	//#ifdef iphone
	let UIPasteboard = objc.import("UIPasteboard"); 
    let pasteBoard = UIPasteboard.generalPasteboard(); 
    pasteBoard.string = self.view.txtName.text; 
    //#endif
    //#ifdef android
    let ClipData = java.import('android.content.ClipData');
    let Contexts = java.import('android.content.Context');
    let VoltMXMain = java.import('com.konylabs.android.KonyMain');
    let context = VoltMXMain.getActivityContext();
    let myClipboard = context.getSystemService(Contexts.CLIPBOARD_SERVICE);
    let myClip = ClipData.newPlainText("", self.view.txtName.text);
    myClipboard.setPrimaryClip(myClip);
    //#endif
    self.view.btnClipBoard.text = "Copy done!";
  }
```
AndroidとiOSでロジックが異なるため、ifdefでデバイスの条件分けをしています。
その他のロジックについては、Widget名だけ注意してこの通りに使えばOKです。

最後にボタンのonClickアクションのEditボタンを押して、
Invoke Functionで`onClickCopy`の関数を設定すれば完了です！
![スクリーンショット 0005-08-07 11.30.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/0863c3eb-d07d-5e94-e09a-b7afa7a07e72.png)


これで完成です！

早速動きを見ていきましょう。
テキストボックスに入力した文字がボタンを押すことでコピーすることができるようになりました！

|iOS|Android|
|--|--|
|![ezgif-3-50b9b0bcb4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/37de8f7a-e696-7d77-1f16-46af57bc87c0.gif)|![ezgif-3-c499a14233.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/f89781c4-0510-2fc5-fa4a-d657f4c1a4a2.gif)|

# 最後に
NFIを使うと聞くと、一見難しそう..!と思われるかもしれませんが、
GUIでNFIを簡単に追加することができるため意外と簡単に実装ができます。
是非これを機会にNFIを活用した実装もチャレンジしてみてくださいね！

# 参考
https://support.hcltechsw.com/community?id=community_question&sys_id=3774d8d11b58e8142518542f0a4bcbd0

https://opensource.hcltechsw.com/volt-mx-docs/docs/documentation/Iris/iris_nf_api_dev_guide/content/common_tasks_for_android.html
iPhoneやiPadからsb3ファイルをギガファイル便でおくろう

# iPhoneやiPadでやるところ

- Scratchのプロジェクトを、sb3ファイルで保存します。
    - sb3ファイルは、iPhoneの中に保存されます。
- ブラウザてギガファイル便にアクセスします。
- 「ファイルの選択」で、sb3ファイルを選択します。
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/d6231ca9-aa74-fc1b-c8f9-b9091b8fbf64.png)

- 「このダウンロードを短くする」をクリックします。
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/9c50851d-a4ab-9698-31be-4cd3a2cc4559.png)


- 新しいタブでページが表示されるので、下へスクロールします。「短縮する」をクリックします。
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/4e7a8d8d-2e70-0b0d-3273-3e4d24c48182.png)


- 短縮URLがつくられます。
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/c46aa33b-da9c-5e5c-af0b-d313140d4e66.png)


# パソコンでやるところ

- iPhoneに表示されている短縮URLを見ながらタイピングしよう。
Room/Hiltのkaptをkspにしてみる

# この記事の内容
GradleのAnnotationProcesserを、kaptからkspにするお話です。

## そもそもAnnotationProcesserって何？
「AnnotationProcesser」は、コンパイルの時にコードを自動生成しましょうという機能です。
これはjavaの機能で、ソースに埋め込まれているアノテーションに基づいてコードを自動生成します。

このAnnotateionProcesserをkotlinで書かれたソースでもできるようにしたのが、「kapt（kotlin annotation processer tools）」です。
で、kaptを高速化させたのが、「KSP（kotlin symbol processing）」になります。

細かい話は、公式ページにお任せしますが、kaptでは、kotlinからjavaのコードに変換することで、Java AnnotaionProcesserが理解できるようにしてから、コードの自動生成を行っていました。
kspは、kotlinから直接コードを自動生成する（javaで中間コードを生成しない）ので早い!らしいです。(ちゃんとはかってませんが、体感できるレベルで早いです)

https://developer.android.com/studio/build/migrate-to-ksp?hl=ja

## RoomとHiltをKSPに移行する

### gradle
[build.gradle](https://github.com/jozuko/WeatherForecast/blob/80878d8eaa8526b8faf1e02a481c972c2c316288/build.gradle)

```diff_gradle:build.gradle
plugins {
    id 'com.android.application' version '8.1.0' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
    id 'org.jetbrains.kotlin.plugin.serialization' version '1.8.10' apply false
    id 'com.google.dagger.hilt.android' version '2.47' apply false
+   id 'com.google.devtools.ksp' version '1.8.10-1.0.9' apply false
}
```

[app/build.gradle](https://github.com/jozuko/WeatherForecast/blob/80878d8eaa8526b8faf1e02a481c972c2c316288/app/build.gradle)

```diff_gradle:app/build.gradle
plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'org.jetbrains.kotlin.plugin.serialization'
-   id 'kotlin-kapt'
+   id 'com.google.devtools.ksp'
    id 'com.google.dagger.hilt.android'
}

android {
    defaultConfig {
-       kapt {
-           arguments {
-               arg("room.schemaLocation", "$projectDir/schemas")
-           }
-       }
+       ksp {
+           arg("room.schemaLocation", "$projectDir/schemas")
+       }
+   }
}

dependencies {
    // hilt
    def hilt_version = "2.47"
    implementation "com.google.dagger:hilt-android:$hilt_version"
-   kapt "com.google.dagger:hilt-compiler:$hilt_version"
+   ksp "com.google.dagger:hilt-compiler:$hilt_version"
    implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'

    // Room
    def room_version = "2.5.2"
    implementation "androidx.room:room-runtime:$room_version"
    implementation "androidx.room:room-ktx:$room_version"
-   kapt "androidx.room:room-compiler:$room_version"
+   ksp "androidx.room:room-compiler:$room_version"
}
```
room.schemaLocationのところは、Roomの設定でexportSchemaがtrueの時に必要な記述です。
星レビューの実装方法


次はコメントの投稿の際に星をつけてレビューする機能の実装方法を教えます。
まず最初にmodelのreview.rbを作成し、関連対象のモデルをbelongs_toを記載します。

```

class Review < ApplicationRecord
  belongs_to :shop
  belongs_to :user
end

```

その後にreview用のマイグレーションファイルを作成し、カラムや関連づけるテーブル名を記載します。

```

class CreateReviews < ActiveRecord::Migration[version]
  def change
    create_table :reviews do |t|
      t.integer :rating
      t.text :comment
      t.references :shop, null: false, foreign_key: true
      t.references :user, null: false, foreign_key: true

      t.timestamps
    end
  end
end

```


次にレビューを投稿するためのレビューフォームを作成します。
app/views/reviewsにrating_form.html.erbを作るのが一般的です。

```
<%= form_with(model: review, url: shop_reviews_path(@shop)) do |form| %>
  <div class="form-group">
    <%= form.label :rating, "評価" %>
    <%= form.select :rating, options_for_select([1, 2, 3, 4, 5]) %>
  </div>
  <div class="form-group">
    <%= form.label :comment, "コメント" %>
    <%= form.text_area :comment %>
  </div>
  <%= form.submit "レビューを投稿", class: "btn btn-primary" %>
<% end %>

```

reviewに関連するコントローラーファイルを作成し、createアクションとパラメーターを作成します。

```

class ReviewsController < ApplicationController
  before_action :set_shop

  def create
    @review = @shop.reviews.build(review_params)
    @review.user = current_user
    if @review.save
      redirect_to @shop, notice: "レビューが投稿されました。"
    else
      render 'shops/show' # エラー時に店舗の詳細ページに戻る
    end
  end

  private

  def set_shop
    @shop = Shop.find(params[:shop_id])
  end

  def review_params#パラメーター
    params.require(:review).permit(:rating, :comment)
  end
end
```

星レビューが付いたコメントを表示する詳細ページのコードはこのようになります。app/views/shops内のshow.html.erbにコードを追加します。

```

<div class="shop-details">
  <!-- ...省略... -->
  <% if @review %>
    <%= render 'reviews/rating_form', review: @review %>
  <% else %>
    <%= render 'reviews/rating_form', review: Review.new %>
  <% end %>
  <!-- ...省略... -->
</div>

```

ルーティングは以下のコードを設置します。

```

patch '/reviews/:id/rate' => 'reviews#rate', as: :rate_review
  resources :shops, only: [:index, :new, :create, :show, :edit, :update, :destroy] do
    member do
      get 'reviews'
    end
    resources :comments, only: [:create, :destroy, :edit, :update]
  end

```

これにより、コメントを投稿する際に5段評価の星をつけることも可能となります。
「Git 基本の使い方33」 - "Git言語"が完全に理解できた

WEBアプリケーション開発のためGit・Sourcetreeを学んだのですが、非常に便利なツールだということが分かったので主な有用性と使い方・一見難解な"Git言語"について簡潔に学習してみました。

# Gitの利点
Gitの利点は、誰がいつ、どのファイルを変更したかを管理できるようになることです。またバージョン管理をすることで「ファイルを消しちゃった！」というケアレスミスを予防できます。
Gitを用いればファイルを管理する集中型管理システム・分散型管理システムを簡単に導入することのも利点です。

- 集中型管理システム→システムを必ず中央システムにつなぐ
- 分散型管理システム→ローカルなリポジトリーを作成する。オフラインでも作業できる他、ファイルを共有することでリモートリポジトリーの復旧が容易になる

# Git機能の有効活用

複数PCにリモートリポジトリーのクローンを作り、複数人でのマルチタスクや個人での仕事場・リモコンワークでの平行作業に活用できます。リモートリポジトリ－を提供しているサービスとしては **Bitbucket・GitHub** 等がある。外部には出せない社内プロジェクトはBitbucket、オープンソース系プロジェクトはGithubで管理するのがおススメとありました。


# Git言語を理解する
Gitを使う障壁となるのが、一見難解な専門用語（笑）の理解です。ここでは「Git 基本の使い方33」を参考に"Git言語"の使い方をまとめてみました。

- リモートリポジトリ（中央リポジトリ）
→プロジェクトの中心となる「完成品」を集めるための場所。
　プロジェクトの管理者がGithub・Bitbucketなどのリポジトリを提供する
　サービスで管理する。

- ローカルリポジトリ
→リモートリポジトリを複製して必要なファイルを個々人のPCで作成（「部品」）する。
　通常ローカルをリモートに反映するにはリモート側の管理者の確認が必要。

- 作業ツリー
→ローカルリポジトリーの中にあるファイル。ステージに追加しないと変更内容には反映されない。

- ステージ
→ローカルリポジトリー中のファイルの内、コミットするとリモートリポジトリーに送信されるファイル

- コミット
→リモートリポジトリーにステージ上のファイルを送信すること。
　コミットには原則、変更内容を伝える「コミットメッセージ」を書く。
　コミットは「ステージに追加→コミット」の2段階で行う。
　また、コミットは1課題・1タスクごとにこまめな修正ができるようにする。
　ファイルに関しては新規追加・削除をするタイミングでコミットする。
　変更箇所をコミットすると、後でその変更箇所を検知することができる。
コミットメッセージ→コミットのタイトル、概要＋変更の目的
※「変更をすぐにmasterにプッシュする」を選ぶとマスターとなるリポジトリに即座に反映される。
 
- クローン
→リモートリポジトリを複製して自分のPCのローカルリポジトリにする

- フォーク
→リモートリポジトリを複製して別のリモートリポジトリにする。通常ローカルリポジトリはオリジナルのリモートリポジトリではなく、フォークした「自分用」のものにコミットするのが冗長的で便利となる。

- プル
→フォークしたリモートリポジトリをローカルリポジトリに複製する。
　
- プッシュ
→ローカルリポジトリの変更を自分用のフォークしたリモートリポジトリに反映する。プルとプッシュの繰り返して自分用のバックアップと作業の進捗ができる。

- プルリクエスト　
→「自分用」のリモートリポジトリをオリジナルに反映するよう要請する。作業が完了したら「変更を確認して反映して下さい」と管理者に伝えるのに使う。

- フェッチ
リモートリポジトリの最新状態）を取得する。

- マージ
ローカルリポジトリをフェッチした内容に変更する。プルはフェッチとマージを順に行うGit上の動作となっている。

- オリジン
リモートリポジトリのある場所


# Git・Bitbucketで作業環境を準備する

https://bitbucket.org

共同作業をするための環境をリモートリポジトリ・ローカルリポジトリで管理する方法
>①中央リポジトリを作成
②中央リポジトリをクローンしてローカルリポジトリを各PCに作成
③ファイルをローカルリポジトリの管理下にする
④ローカルリポジトリを初回コミット→プッシュし、ファイルを中央リポジトリと同期する
⑤準備完了

ファイルを変更したらコミットしてバグ等を起こさない安定版・追加で機能を追加した不安定版のテストを両方保管する、という使い方ができますね。
Irisのビルド時にStartup form is not part of build for XX channelとエラーが表示されたときの対処法

# 目次
1. はじめに
1. 解消方法

# はじめに
Irisでアプリをビルドする際スタートアップ画面を設定しているにもかかわらず、
下記のようなメッセージが表示されビルドができない場合の対処法について説明します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/f99c54af-7047-40de-5506-f3d8a6e4d4c4.png)

# 解消方法
このエラーは、フォーム毎にグループ分けをしている場合、稀に発生します。

エラーを解消するには、ビルドをしたい対象のグループを右クリックし、
「Include in build」をクリックすることで解消することができます。 

こうすることによって、対象のグループをビルドに含めることができ、
正常にビルドができるようになります。 
![スクリーンショット 0005-08-07 10.12.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/9edb671e-11ea-ce4a-7e74-2ba9c4b72f83.png)

また、逆に対象のグループをビルドに含めたくない場合は、
「Exclude from build」をクリックすることでビルド対象から除外することができます。

# 最後に
同じように困った人がいたら、是非参考にしてみてくださいね！
かっこいいリモートワーク作業環境をつくりたい

## はじめに
コロナ前後でたくさんのことが大きく変化したと思いますが、そのひとつが**リモートワーク環境＝PCデスク環境の充実**だと思います。

フリーランスで自宅が作業場だった、という人以外は、大半の時間をオフィスで過ごしていたわけですので、自宅の作業場にお金をかけるというのは、あまりなかったと思います。

リモートワーク環境は、作業していて **気持ちがあがる環境＝自分が思うかっこいい環境** にしたいという思いが強いです。

かっこいい重視で、単純にいろいろな方のデスク環境を眺めているのが好きです。

## ずっと見てられる他人のPCデスク環境

Youtubeなんかでも見れますが、2つほど紹介です。

下記のサイトはずっと見てられます(感謝)。私にとっては時間泥棒。
1つとして同じ部屋はないので、個性が全開で、それぞれの「好き」や「こだわり」が詰まっている感じがします。

https://watchmono.com/e/show-your-pc-desk-part315

https://www.workspaces.xyz


## なにから揃えるか

個人的意見ですが、基本的な必須アイテムは以下の7つだと思います。

#### ①机
やはり電動昇降デスクがおすすめ。時々立って作業ができるのが、これほど気分転換になるとは思いませんでした。有名どころは、FlexiSpotかと思います。

https://www.flexispot.jp/

#### ②椅子　
一番投資すべき、と言い切る人が多い椅子ですが、高いものを選べはよいということではなく、相性はあると思います。私はオカムラのオフィスチェアを使用して概ね満足していますが、ハーマンミラーなど上を見ればきりがありません。またゲーミングチェアがしっくりくるという方もいるかと思います。とにかく、買う前に試し座りをしてみて検討する以外にないと思います。

https://www.okamura.co.jp/company/ws202x/home/chair/

#### ③ディスプレイ
4K USB-C 接続がおすすめです。ケーブル１本で電源供給もしてくれるなんてすばらしいの一言です。（下のリンクは32インチですが、27インチでも十分です）

https://www.dell.com/ja-jp/shop/dell-%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E3%83%8F%E3%82%A4%E3%82%A8%E3%83%B3%E3%83%89%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-u3223qe-315%E3%82%A4%E3%83%B3%E3%83%81-4k-hdr-usb-c-hub-%E3%83%A2%E3%83%8B%E3%82%BF/apd/210-bebl/%E3%83%A2%E3%83%8B%E3%82%BF%E3%83%BC-%E3%83%A2%E3%83%8B%E3%82%BF%E3%83%BC%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B5%E3%83%AA%E3%83%BC

#### ④キーボード・⑤マウス
こちらも椅子と一緒で相性があると思います。私は、Logicool一択です。
今まで、USBにしろBluetoothにしろ、無線接続はしっくりときませんでしたが、LogiのLOGI BOLT方式で、無線接続に違和感がなくなりました（特にマウスについて）
また、私はWINDOWSとMACを行き来することがあるので、Flow機能もとても重宝しています。

https://www.logicool.co.jp/ja-jp/products/keyboards/mx-keys-mini.920-010517.html

#### ⑥モニターライト
ディスプレイにかけるモニターライトもディスプレイと同時に揃えておくとよいと思います。電源がディスプレイからとれるので、ケーブルが邪魔にならないですし、場所もとりません。ディスプレイへの映り込みもないので、完璧です。

https://www.benq.com/ja-jp/lighting/screenbar-lamp/screenbar-halo.html?gclid=Cj0KCQjwoK2mBhDzARIsADGbjerYtw_jqKQmq3ik6GHvZmdjLKWSqujUilMT2DRve8WGl20C4W1N4VQaArAjEALw_wcB

#### ⑦モニターアーム
ディスプレイモニターを浮かせるとスペースに余裕ができて、仕事にも余裕ができます（と勝手に思います）。なにより気分があがります。

https://www.ergotron.com/ja-jp/%E8%A3%BD%E5%93%81/%E3%83%A2%E3%83%8B%E3%82%BF%E3%83%BC%E3%82%A2%E3%83%BC%E3%83%A0

## おまけ１：テープライトを活用する
気分があがる環境のレベルアップは、何と言ってもLEDテープライトを活用するだと思います。スマホや声で操作できるものもあります。

https://moaipapablog.com/recommend-ledtape-light/

## おまけ２：ケーブルにこだわる
ケーブルにこだわりだすとさらにレベルアップだと思います。私もケーブル嫌いでとにかくスッキリさせておきたい派なので、少し前の記事ですが参考になります。

https://note.com/goando/n/n8569df97318c?magazine_key=me3ed2026f6ac

## まとめ
あれがいい、これがいいというのも大事ですが、仕事や作業をしていて、自分の気分があがる環境をつくることが一番だと思います。
Go言語向けNCMB SDKの使い方（データストアの検索）

NCMBはモバイル向けのBaaS（mobile Backend as a Service）ですが、サーバー側のデータとNCMB上のデータを連係させたいというニーズは良くあります。

そんなときには各言語向けのSDKがあると便利です。サーバー向けにはRuby、Python、PHP、Java、C#のSDKがあります（すべて公式サポート対象外の、コミュニティSDKという位置づけです）。

今回はGo言語向けのSDK開発をはじめたので、その使い方を紹介します。まずはデータストアへのデータ保存についてです。

## ソースコード

ソースコードはGitHubにて公開しています。ライセンスはMIT Licenseになります。

[NCMBMania/ncmb\_go](https://github.com/NCMBMania/ncmb_go)

## インストール

SDKのインストールは下記コマンドで行います。

```bash
go get -u github.com/NCMBMania/ncmb_go
```

## インポート

続けてSDKをインポートします。

```go
import (
    "github.com/NCMBMania/ncmb_go"
)
```

## 初期化

NCMBより取得したアプリケーションキー、クライアントキーを使って初期化します。

```go
ncmb := NCMB.Initialize("YOUR_APPLICATION_KEY", "YOUR_CLIENT_KEY")
```

### データの検索

データの検索には Query を使います。引数は検索対象のクラス名です。

```go
query := ncmb.Query("Hello")
```

後は条件を指定して、 `FetchAll` メソッドでItemの配列が取得できます。

```go
query := ncmb.Query("Hello")
query.EqualTo("msg1", "Hello")
items, err := query.FetchAll()
if err != nil {
	fmt.Println(err)
}
fmt.Println(items[0].GetDate("createDate"))
```

利用できる検索条件（オペランド）は以下の通りです。

| メソッド | 説明 |
| --- | --- |
| EqualTo(key string, value interface{}) | 指定したキーの値が指定した値と等しいアイテムを取得する |
| NotEqualTo(key string, value interface{}) | 指定したキーの値が指定した値と等しくないアイテムを取得する |
| LessThan(key string, value interface{}) | 指定したキーの値が指定した値未満のアイテムを取得する |
| LessThanOrEqualTo(key string, value interface{}) | 指定したキーの値が指定した値以下のアイテムを取得する |
| GreaterThan(key string, value interface{}) | 指定したキーの値が指定した値より大きいアイテムを取得する |
| GreaterThanOrEqualTo(key string, value interface{}) | 指定したキーの値が指定した値以上のアイテムを取得する |
| In(key string, value interface{}) | 指定したキーの値が指定した配列のいずれかと等しいアイテムを取得する |
| NotIn(key string, value interface{}) | 指定したキーの値が指定した配列のいずれとも等しくないアイテムを取得する |
| Exists(key string, value interface{}) | 指定したキーが存在するアイテムを取得する |
| RegularExpression(key string, value string) | 指定したキーの値が指定した正規表現にマッチするアイテムを取得する |
| InArray(key string, value interface{}) | 指定したキーの値が指定した配列のいずれかを含むアイテムを取得する |
| NotInArray(key string, value interface{}) | 指定したキーの値が指定した配列のいずれを含まないアイテムを取得する |
| AllInArray(key string, value interface{}) | 指定したキーの値が指定した配列のすべてを含むアイテムを取得する |
| Near(key string, value GeoPoint) | 指定したキーの値が指定した地点の近くにあるアイテムを取得する |
| WithinKilometers(key string, value GeoPoint, distance float64) | 指定したキーの値が指定した地点から指定した距離以内にあるアイテムを取得する |
| WithinMiles(key string, value GeoPoint, distance float64) | 指定したキーの値が指定した地点から指定した距離以内にあるアイテムを取得する |
| WithinRadians(key string, value GeoPoint, distance float64) | 指定したキーの値が指定した地点から指定した距離以内にあるアイテムを取得する |
| WithinSquare(key string, southWest GeoPoint, northEast GeoPoint) | 指定したキーの値が指定した範囲内にあるアイテムを取得する |

また、以下も条件として追加できます。

| プロパティ | 説明 |
| --- | --- |
| Limit | 取得する件数を絞り込みます（デフォルト10。最大1000） |
| Order | データの並び順を指定します |
| Skip | データの取得をスキップする件数を指定します |

## まとめ

まだ基本的な機能しかありませんが、徐々にバージョンアップしていきます。

Go言語を使ってWebアプリケーションを開発している方は、そのデータ保存先としてNCMBを利用してみてください。

[mBaaSでサーバー開発不要！ \| ニフクラ mobile backend](https://mbaas.nifcloud.com/)
5分間でマネジメントの入口を理解する

## この記事の目的
- マネジメントって何ですか?
- 具体的に何をしたらいいですか?

といった質問を最近受けたので、意外と需要あるかと思い記事にしました。
出来る限り短く書いたので最後までみてもらえると喜びます。

## Who are you
自分は2つの業界と3つの会社で約10年ほどマネジメントを経験してきました。
- 10名の新卒専任教育(半年を3回経験)
- 2~30名のマネジメント(転勤族だったので5店舗で経験)
- 500名の労働組合組織運営
- 20名のエンジニアマネージャー

## マネジメントとは何か
与えられた資源で最大限の結果を出すための手法

https://dictionary.sanseido-publ.co.jp/column/%E7%AC%AC11%E5%9B%9E-%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A1%E3%83%B3%E3%83%88

manegeは `管理` と思う方も多いですが、「なんとかする」が正しい意味です。

### もうちょっと細分化

![マネジメント図解.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534071/27b80c42-4be5-fb1f-87fa-4552aa15f907.jpeg)

下から順番に説明します。

#### 人として基本的な感覚

例えば「すいません。身内で不幸があり...」という連絡を受けた時に
`「大丈夫?」` という第一声がでるかどうかです。
意外と先に仕事の確認などをする人もいますが話す順番が違うだけでも印象が変わります。

信頼関係が成り立たないとパフォーマンスを上げるための行動なんてできませんし、
最悪の場合管理もできない無法地帯になることもあります。
**まずは土台に信頼があります。**

#### 管理スキル

次に必ず管理スキルが求められます。
チームメンバーにそれぞれマイルストーンがあるはずなので、
- 達成できそうか?
- 達成できない場合はどのように対応するか?

といったことを管理できているかが求められます。
管理するためには各個人のスキルとアサインされているタスクの難易度の把握が最低限必要です。

#### パフォーマンスを底上げするスキル

以下は同列です。場面に応じて使い分けていく必要があります。

- 教育
- 整備(環境)
- 配置(適材適所)

##### 教育
コーチングからティーチングまで幅広く。相手に合わせて。
↓こんな記事も書いてるので良かったらご覧ください。

https://qiita.com/baan_nasebanaru/items/c789f5655465fa641338

##### 整備(環境)
例えば「技術的なスキルは高いが、顧客折衝が苦手」なAさんが顧客折衝の対応をしている時に
- さっと間に入ってフォローする
- そもそも顧客折衝しなくて済むように事前に必要な情報を揃える

などを行えるかどうか。

##### 配置(適材適所)
整備と少し似ています。そもそものアサインを変更しましょう。
案件との相性もありますし、人と人なので相性も当然あります。
短期 ~ 長期的な視点で配置転換を必要に応じて行うことも重要な仕事です。

## まとめ
組織や企業の運営は非常に複雑です。
初めてマネジメント職を経験するとその複雑さから矛盾を感じしんどくなることがあります。
組織の秩序のためにはプロセスを踏む必要がありますが、プロセスを重視し過ぎるとなかなか結果もついてこなかったりします。
また、結果の重圧に負けると管理ばかりに比重がいってしまい、いつの間にか「自分が嫌いだった上司」をなぞっているなんてこともあったり、プロセスを度外視した方法に出たりします。

ですが、大事なことは
**部下と会社、この両方から信頼を勝ち取ること**
これだけです。

そのためにまずは管理できている状態になる。
会社からの信頼をとれると予算(人/物/金/情報)を持ってこれるようになります。
そして、管理だけではなく対話を重ねて部下のパフォーマンスを上げることで、バランスの取れた良いチームになっていくのかなと思います。
(管理とパフォーマンスアップのバランスが難しいですが、try & errorを繰り返せば自ずと引き出しが増えると思います)

この記事が、これからマネジメントを初めて行うという方の一助になれれば幸いです。
kintone.Promise が （非推奨）になってた

kintone.Promise がいつの間にか（非推奨）になっていたので、メモ

# 概要

[kintone.Promise を使用する（非推奨）](https://cybozu.dev/ja/kintone/docs/js-api/other/kintone-promise/)

>cybozu.com で動作保証しているすべての Web ブラウザーで、 ブラウザーの Promise (External link) を利用可能です。
kintone.Promise は使わず、ブラウザーの Promise を使うことを推奨します。

IE が廃止になり、IE をサポートしていたkintone.Promise の役割は終わったということですね。
これまで多くのカスタマイズ・プラグインが kintone.Promise で開発されてきたので、廃止は当分ないと思いますが、今後 Promise を使う場合は、ブラウザーの Promise を使ってくださいということ。

cybozu developer network のサンプルコード等は、まだ kintone.Promise のままですが、そのうち変更されるかも。


# 対応

単純に、kintone.Promise を Promise に変更するだけです。

```kintonePromise.js
let p1 = new kintone.Promise(function (resolve, reject) {

```

```Promise.js
let p1 = new Promise(function (resolve, reject) {

```
resource can't be used as a merge field.


+ [resource can't be used as a merge field.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A977xSAB)

:::note
Turns out I had the Variable in my formula and you need to "Record (Single) Variable" in. It worked on my other flow because the API of the variable on the one iwth the issue was the same as the "Record (Single) Variable" on the other flow.
:::

+ [未解決：The "Find_a_Match.Id" resource can't be used as a merge field.](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000CfExnSAF)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8b5f6cec-af59-8939-40da-9359f6c86816.png)

+ [The "Find_a_Match.Cintact.Id" resource can't be used as a magerge field](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V000079RzE2)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b2efd7c8-783d-9de3-ae31-c5d7d887ba3b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/3753e506-e084-be89-55d8-75dda23e4fee.png)

+ [The "Find_a_Match.Id" resource can't be used as a merge field.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JfnRTSAZ)

ベストサンサーを見ても解決策は全く理解できませんね。

So my issues is solved, some refresh/caching problem going on there I think since field which was not available before is available now thanks to Trevor and Mikey for their input!

キャッシュの問題とか言っているけど...
MySQL 5.7で日本語データを入力できない時の対処法

# 要約
MySQL5.7で日本語データを入力すると以下のエラーが表示された。
```
1366: Incorrect string value: '\xE4...' for column 'question' at row 1
```
ぶつかった壁が2つあったのでまとめる。
1. DB構築の壁(Dockerで構築している場合)
1. テーブルの壁

# 前提
- M2 MacBook Air
- MySQL ５.７
- Docker Desktop使用
docker-composeでMySQL構築（説明サイトがたくさんありますので割愛)

# 1. DB構築の壁(Dockerで構築している場合)

my.cnfに日本語データ入力するための記述を記載してMySQLを再起動。（説明サイトがたくさんありますので割愛)
```my.cnf
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_bin
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqldump]
default-character-set=utf8mb4
```
`SHOW VARIABLES LIKE 'chara%';`を実行すると一部がlatinになっている。

|Variable_name|Value|
|-|-|
|character_set_client|utf8mb4|
|character_set_connection|utf8mb4|
|character_set_database|latin1|
|character_set_filesystem|binary|
|character_set_results|utf8mb4|
|character_set_server|latin1|
|character_set_system|utf8|
|character_sets_dir|/usr/share/mysql/charsets/|

docker-compse.ymlの内容は以下の通り。分かりやすくするため間違いと正解を同時に記載しています。
`my.cnf`を適当に配置して記述したのが間違い。(`./docker-compose.yml`と並列に`./conf/my.cnf`で配置）
```docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    container_name: mysql
    platform: linux/amd64
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${ROOT_PASS}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASS}
      TZ: ${TZ}
    ports:
        - ${DB_PORT}:3306
    volumes:
        - db-store:/var/lib/mysql
  　　　　　　   - ./conf/my.cnf:/etc/mysql/conf.d/my.cnf　　　　（間違い)
　　　　   　　  - ./conf:/etc/mysql/conf.d                (正解)
volumes:
  db-store:
```

## 対策
Docker DesktopのTerminalからログイン
```
Containers > Nameのリンクをクリック　> Logs/Inspect/Terminal/Files/Statusの中からTerminal
```
my.cnfの場所を探す。
```sh
sh-4.2# mysql --help | grep my.cnf
                      order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf 
```
存在した/etc/my.cnfの中身をチェック
```
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
```
docker-compose.ymlのmy.cnfの位置を変更。ディレクトリとファイルを間違えていた。
```yml
  　　　　　　   - ./conf/my.cnf:/etc/mysql/conf.d/my.cnf　　　　（間違い)
　　　　   　　  - ./conf:/etc/mysql/conf.d                (正解)
```

# 2. データベースの壁

日本語データ入力をリトライするもエラーメッセージが出る。
`SHOW VARIABLES LIKE 'chara%';`を実行すると正しく設定されている。

|Variable_name|Value|
|-|-|
|character_set_client|utf8mb4|
|character_set_connection|utf8mb4|
|character_set_database|utf8mb4|
|character_set_filesystem|binary|
|character_set_results|utf8mb4|
|character_set_server|utf8mb4|
|character_set_system|utf8|
|character_sets_dir|/usr/share/mysql/charsets/|

## 対策

カラムの定義を変更する必要があった。
```sql
ALTER TABLE テーブル名 CHANGE 旧カラム名 新カラム名 VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

これでエラーは解消しました。

以上