OmniAICreator/Qiita-1.07M huggingface dataset:
Github(初期設定からリモートリポジトリにプッシュ)

# Github(初期設定)

・まずはGithubに新規登録する(https://github.co.jp/)

・ターミナルにて以下のコマンドを実行する
```
$ git config --global user.name <Githubに登録したユーザー名>

$ git config --global user.email <Githubに登録したメアド>
```
・Githubで使うエディタを登録(今回はVScodeを使用)
```
$ git config --global core.editor 'code --wait'
```
・作業ディレクトリに移動し、以下のコマンドを実行する
```
$ git init (ローカルリポジトリを作成する)
```

・以下のコマンドを実行し、現在のローカルリポジトリにリモートのリポジトリを追加する。（現在のローカルリポジトリに、「origin」という名前で、《GithubのURL》をリモートリポジトリとして追加する）
```
$ git remote add origin <GithubのURL>
```
# ワークツリーからリモートリポジトリへプッシュ

![Github仕組み.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/36ed985b-c940-1b7a-02b3-fbb259ac6ea6.jpeg)


```
$ git add <ファイル名>　　　(ワークツリーからステージングエリアに追加)
/// ("."もしくわ"-A"のオプションで全てのファイルが対象)

$ git status　　　(ステージングエリアに追加したファイルを確認)

$ git commit -m <コミットメッセージ>　　　(ローカルリポジトリに変更内容を取り込む)

$ git push <リモートリポジトリ名>　　　<ローカルリポジトリ名>
(ローカルリポジトリの変更点をリモートリポジトリに変更内容を取り込む)
(例: git push origin master)
```

# その他使えるGitコマンド一覧

### ファイルの差分を確認する
```
$ git diff <ファイル名>　　　(git addする前の変更差分)
/// ("--cached"オプションで git addした後の変更差分)
```

### 変更履歴を確認

```
$ git log (変更履歴を確認)
/// ("--oneline"オプションでログを一行で表示して見やすくする)

$ git log -p <ファイル名>　　　（ファイルの差分を表示）
```
### ファイルの削除
```
$ git rm <ファイル名>　　　(ワークツリーとステージングエリアのファイルが削除)

$ git rm -r <ディレクトリ>  (ワークツリーとステージングエリアのディレクトリ削除)

$ git checkout <ファイル名 or ディレクトリ名>  (ステージングエリアとローカルリポジトリが削除)

$ git rm --cached <ファイル名>　　　　(コミットしたリポジトリのファイルだけ削除)
```

### 変更を取り消す
```
$ git reset HEAD <ファイル名> or <フォルダ名>
(ステージした変更を取り消す)

$ git reset HEAD  (全変更を取り消す)

$ git commit --amend  (直前のコミットを取り消す)
///  (ただし、リモートリポジトリにプッシュしたもは取り消しできない)
```
※ HEADは今いる作業している場所、ポインタのこと

# 参考
https://atmarkit.itmedia.co.jp/ait/articles/2005/08/news017.html#sample2

https://qiita.com/shibukk/items/8c9362a5bd399b9c56be

Git： もう怖くないGit！チーム開発で必要なGitを完全マスター (Udemy)
あるコミットで何をしたかを見る

# ```git show```
直近のコミット（HEADが指しているコミット)の情報を表示する。
```
********@mbp training % git show
commit ************************* (HEAD -> master)
Author: ******* <******************>
Date:   Sun Jun 12 16:39:42 2022 +0900

    演習課題 hello.txtを新しくコミットする

diff --git a/hello.txt b/hello.txt
new file mode 100644
index 0000000..10ddd6d
--- /dev/null
+++ b/hello.txt
@@ -0,0 +1 @@
+Hello!
```
直近のコミット名、hello.txtのファイルを作成,Hello!の追加されたことがわかる。

```
*************@mbp training % git show HEAD^
commit ****************
Author: ******* <**************>
Date:   Sun Jun 12 16:37:50 2022 +0900

    演習課題 RAEDME.mdを修正

diff --git a/README.md b/README.md
index *****************
--- a/README.md
+++ b/README.md
@@ -1 +1,3 @@
-this is a test project.
+This is a test project for Git.
+Contents:

+* hello.txt
```
```HEAD^```と指定すると直近のコミットよりひとつ前のコミットの情報を表示できる。

# 演習
```
***********@mbp training % git show HEAD^
commit **************
Author: ****** <************>
Date:   Sun Jun 12 16:37:50 2022 +0900

    演習課題 RAEDME.mdを修正

diff --git a/README.md b/README.md
index *****************
--- a/README.md
+++ b/README.md
@@ -1 +1,3 @@
-this is a test project.
+This is a test project for Git.
+Contents:
+* hello.txt
*********@mbp training % git show ********
commit ************
Author: ******* <************>
Date:   Sun Jun 12 16:37:50 2022 +0900

    演習課題 RAEDME.mdを修正

diff --git a/README.md b/README.md
index *************
--- a/README.md
+++ b/README.md
@@ -1 +1,3 @@
-this is a test project.
+This is a test project for Git.
+Contents:
+* hello.txt
```
ハッシュ値でも呼び出せた。
表示内容が同じことがわかる。
単体テストと統合テスト

単体テストと統合テストの違いについて学習したため、備忘録として残しておきます。
参考にさせていただいた記事はこちらです。▼
[システム開発の工程の「単体テスト」と「結合テスト」の違いを徹底解説！](https://and-engineer.com/articles/X_-EBRAAACcAJnau)

# 単体テストと統合テスト

- システム開発の工程の1つ。

# よくあるシステム開発の流れ

1. 要件定義
2. 外部設計
3. 内部設計
4. プログラミング（構築）
5. 単体テスト
6. 結合テスト
7. システムテスト
8. 運用テスト
9. システム移行

# 単体テストとは

#### 一言で
- プログラミングの対象単位ごとに行うテスト。
- この単位をモジュールと呼んだりする。
- 単純作業になりがちなこともあり、効率が求められる工程でもある。
- (例)モデルクラスごと

#### 詳細
- 別名：ユニットテスト
- 1つの画面、1つの機能(関数)など、小さな単位ごとに行うテストなのが特徴。
- 条件分岐を網羅する。
- 手法は2種類ある。「ホワイトボックステスト」と「ブラックボックステスト」。
- 「単体テスト仕様書」に則って実施する。

#### ホワイトボックステストとは
- プログラムが設計したとおりに動作するかを1つ1つ網羅的に確認するテスト手法。
- つまり、「開発者側の視点」にたったテストと言える。
- 例：設計書に「エラーが発生する」と定義されている文字列を入力してみて、出力結果が正常かどうか検証する。
- メリット：1つ1つのモジュールに対して網羅的に検証できること
- デメリット：工数増

#### ブラックボックステストとは
- 開発するシステム自体の仕様を満たしているかどうかを確認する機能のテスト手法。
- つまり、「利用者側の視点」にたったテストと言える。
- 内部のプログラムについては考慮しないため、「ホワイトボックス」とは逆の「ブラックボックス」と呼ばれる。
- 例:設計書に「0～100までの数値」を「正常」と設定した場合、境界付近である値（例えば、0、-1など）を選んでテストする。
- 理由：境界付近にプログラムの欠陥が多いため。
- メリット：利用者の要件を満たしていることが確認できるため、工数を抑えることができること
- デメリット:プログラムの内部処理が適切に行われているかが分からないこと

# 統合テストとは

#### 一言で

- 複数のモジュールを組み合わせて行うテスト。
- テスト項目の洗い出しが難しい。
- （例）ユーザーの新規登録用画面から値を入力、送信して、データベースにレコードが追加されるまでの流れ

#### 詳細
- 別名：コンバインドテスト（combine：組み合わせる）
- モジュール同士を結合させたときに設計通りに動作するか、想定外のエラーが出てもシステム要件が満たされているかを検証するのが特徴。
- 単体テストで正常を確認できたモジュール同士を組み合わせたり、その他の外部モジュールを結合したテストを行ったり。
- 単体テストの結果、1つ1つの機能にエラーがなかったとしても、連携させると問題が発生するケースがあるため、システムの全体的なデータの流れを把握ができる技術が求められる。
- 手法は2種類ある。「インターフェーステスト」と「ブラックボックステスト」。

#### インターフェーステストとは
- 定番のテスト手法。
- 「連結テスト」とも呼ばれる。
- インターフェースとは、モジュール同士を接続したときに、データの引き渡しを仲介する仕組みのこと。
- 機能間やモジュール間でデータを引き渡す際に、引き渡されるべきデータがきちんと引き渡されているか、連携に関わるモジュールが設計した通りに正常に動作しているかなどを検証する。

#### ブラックボックステストとは
- 上述の通りで、プログラムの内部構造を考慮せず、入力に対して正常な出力結果を得ることができるか検証するテスト。
- 結合テストの場合では、単体テストで正常を確認できたモジュール同士を結合してブラックボックステストを実施することで、仕様を満たしているかどうかを確認する。
Gitトークンを作成してみた

# はじめに
git トークンを作成してみたので記事を投稿します。

## トークンの作成

__① 任意のページの右上で、プロフィール画像をクリックします。
続いてSettings(設定)をクリック__

![ss.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/f10f5fc7-4d85-f884-4136-634d137e03c8.jpeg)

__② <>Developer settingsをクリックします__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/c66644b6-b83e-b973-bd68-8032a919fd0b.png)

__③ 左のサイドバーでPersonal access tokens（個人アクセストークン）をクリックする。__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/997f208c-cb1b-1034-5bb2-d99a481bd9aa.png)

__④ [Generate new token] をクリックする。__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/41e8b549-906d-9444-1e31-9a43971c9020.png)

__⑤ トークンにわかりやすい名前をつける。__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/50544393-f6a5-b36c-7d1e-3d4b1bd08db4.png)
__⑥ トークンの期限をつける__
今回は、私は7日にしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/778012df-619c-d43d-fc78-761b83d48612.png)
__⑦ このトークンに付与するスコープ、すなわち権限を選択。__
トークンを使用してコマンドラインからリポジトリにアクセスするには、[repo] を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/36003a70-ce4d-5d41-4c93-70375a86ebd3.png)
__⑧  [Generate token] をクリックする。__
特に何もなければGenerate tokenをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/1e4b2fa8-90b1-753f-0547-f2ae11972594.png)

__⑨ トークン作成完了__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724196/4e0922a2-5987-d622-111c-3e8f540976b2.png)

` 警告: 
トークンはパスワードのように扱い、秘密にしてください。 API を操作する場合は、トークンをプログラムにハードコーディングするのではなく、環境変数として使用してください。 `
HomebrewでPHP7.3インストールする方法2022年版

## まえがき
業務上、PHP8.1とPHP7.3を行き来して作業する必要があったのですが
Homebrewを使ってPHP8.1 → 7.3に切り替えようとしたところ「古いバージョンだからbrew上で管理してないよ！だからインストール出来ないよ！」というエラーが発生。

結構苦労したので、備忘録代わりにメモ。

## 前提
環境は以下の通りです。

macOS Monterey 12.2.1
Homebrew 3.5.2
PHP 8.1（インストール済み）　→　7.3（インストールしたい）

## やり方
元々PHPがインストールされていない場合、1行目は不要です。
また、バージョンは各自インストールされているバージョンを指定します。

```
$ brew unlink php@8.1
$ brew tap shivammathur/php
$ brew reinstall shivammathur/php/php@7.3
```

パス修正する
```
$ vi ~/.zshrc
$ source ~/.zshrc
```

これでOK。

## ちなみに
7.3から8.1に戻すときは普通にやればOK。
```
$ brew unlink php@7.3 && brew link --force --overwrite php@8.1
```
PHPでループの要素を参照渡しにするときの注意

PHPのループで参照渡しを使ったコードが思い通りの挙動にならず、いろいろ調べてたら面白い例を見つけたので紹介。

こんなコードがあったとする。
```php
$a = array('a', 'b', 'c', 'd');

foreach ($a as &$v) {}

print_r($a);

foreach ($a as $v) {}

print_r($a);
```
2回の`print_r($a);`の結果は同じになりそうなものだけど実際は以下のようになる。
```
Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => d
)
Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => c
)

```
なぜかというと、まず1個目のループは参照渡しなので、
```
$vがaが入ってる1個目のコンテナ（※）を指す
$vがbが入ってる2個目コンテナを指す
$vがcが入ってる3個目コンテナを指す
$vがdが入ってる4個目コンテナを指す
```
という流れで`$v`のポインターが4個目のコンテナに移動する。

※コンテナ = 値の格納場所。「zval」とも呼ばれる

2個目のループの間`$v`は4個目のコンテナに対するポインターとして機能しているので、
```
$v=aで4個目のコンテナの中身がaになる
$v=bで4個目のコンテナの中身がbになる 
$v=cで4個目のコンテナの中身がcになる 
```
という現象が起き、上記の時点で配列の中身が`abcc`になってしまう。

対策としては、一個目の配列の後に`unset($v)`で`$v`→4個目のコンテナの参照を切ると解消される。
```php
$a = array('a', 'b', 'c', 'd');

foreach ($a as &$v) {}

print_r($a);

unset($v);

foreach ($a as $v) {}

print_r($a);
```
```
Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => d
)
Array
(
    [0] => a
    [1] => b
    [2] => c
    [3] => d
)
```

## 参考
https://schlueters.de/blog/archives/141-References-and-foreach.html
SESAME4のAPI設定

![スクリーンショット 2022-06-28 15.28.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/8314b457-ddd1-e908-1a07-5b15b064c720.png)
まずSESAMEのスマホアプリをインストールし、
![スクリーンショット 2022-06-28 15.44.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/c7f96cd5-9d22-5ab4-c493-41aff16a8038.png)
こちらをクリックし、下記画面からQRコードを取得してスクショ等で保存します。WiFiモジュール(別売り)も用意し登録しておきましょう。
![スクリーンショット 2022-06-28 15.39.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/9c76c1c9-88e8-7c7b-7d18-772815555a09.png)
[こちらへメールアドレスを入力して頂きAPIキーを取得します。](https://partners.candyhouse.co/login/)
![スクリーンショット 2022-06-28 15.56.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/7e978237-f8f6-d2a0-58e2-f36a261aae18.png)
下記画面になりAPIキーを確認したら、QRコード読み取りボタンから先ほど保存したQR画像を読み込むとUUIDとシークレットキーが取得できます。
![スクリーンショット 2022-06-28 16.10.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/9e3282b0-6d1c-f503-43b7-89acd889581c.png)
あとは環境変数に上記３点を入れればコードから使用出来るようになります。下記コードは、`デバイスを操作`ボタンを押した時と同じ動作が実行できる`toggle()`関数です。
```sesame.ts
import axios from 'axios'
import env from './env'

const aesCmac = require('node-aes-cmac').aesCmac;

export let toggle = async () => {

    const { sesameId, sesameApiKey, keySecretHex } = env.sesame
    let cmd = 82  //(toggle:88,lock:82,unlock:83)
    let history = "Toggled via API"
    let base64_history = Buffer.from(history).toString('base64');

    let sign = generateRandomTag(keySecretHex)
    let after_cmd = await axios({
        method: 'post',
        url: `https://app.candyhouse.co/api/sesame2/${sesameId}/cmd`,
        headers: { 'x-api-key': sesameApiKey },
        data: {
            cmd: cmd,
            history: base64_history,
            sign: sign
        }
    })
};

function generateRandomTag(secret: any) {
    let key = Buffer.from(secret, 'hex')
    const date = Math.floor(Date.now() / 1000);
    const dateDate = Buffer.allocUnsafe(4);
    dateDate.writeUInt32LE(date);
    const message = Buffer.from(dateDate.slice(1, 4));
    return aesCmac(key, message);
}
```
GitHubから1ファイルだけブラウザでダウンロードする

GitHubのレポジトリからレポジトリ全体ではなく、1ファイルだけダウンロードしたいことがあります。curlなどを使う手もありますが、Privateレポジトリだと認証も必要なのでブラウザからダウンロードしたいと思います。

バイナリファイルならダウンロードボタンがありますが、ソースコードやCSVなどはプレビューが開いてしまいます。


このような場合には、ファイルを開き、「Raw」ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/0c136022-18af-4e1c-8cca-4480a7486413.png)

右クリックで「名前を付けて保存」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f944ddfc-6db1-72ee-1057-325015a19d51.png)


「.txt」で保存しようとするので、適切な拡張子に付け替えます。例えばnotebookなら[.ipynb」です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/fff82463-a3b6-855b-a7c8-474829705cf3.png)

これでダウンロード可能です。
Create Report and Dashboard Foldersでのエラーのまとめ

ここでのエラーもよく目にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e32a1c95-aada-27aa-99f7-db6e15e37e39.png)


[I could not find " Marketing Reports" from Global Sales Reports folder. ](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Hmb8h)

フォルダーを作ってなかったようです。


# Could not find a report folder with the name 'Global Sales Reports'. 

+ [Create Report and Dashboard Folders task Could not find a report folder with the name 'Global Sales Reports'. I finished all steps but still not able to finish the task.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007CJhgE)

:::note
I think  should create another playground and follow all the steps.
:::
Jupyter NotebookをMacにインストールした方法

Homebrewのアップデートを行ったら(?)Jupyterがなくなってしまった(?)のでインストールした。
以下のことを記す。

- Jupyter Notebookのインストール
- Jupyter Notebookの立ち上げ方
- Jupyter Labについて

図の描き方はまた別記事にしたいと思う。

# はじめに

前提知識は以下の通りである。

- macOS
- python3はすでに入っている

[Jupyter Notebook](https://jupyter.org/)は図を作成するときに使っている。
合う合わないはあると思うが、私は使いやすいと思っている。

# Jupyter Notebookのインストール

Jupyterがなくなってしまった。

~~~
% jupyter --version
zsh: command not found: jupyter
~~~

まずはpython, pipのバージョン確認。

~~~
% python --version
Python 2.7.18
% python3 --version
Python 3.9.12
% pip --version
pip 20.2.3 from /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/site-packages/pip (python 3.8)
% pip3 --version
pip 22.0.4 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)
~~~

残念ながら私はpython, pipには詳しくない。
コマンドは面倒だけどpython3のままにしてある。

たぶんpip3でインストールすれば良いのだろう。

~~~
% pip3 install jupyter
~~~

できたっぽい。

~~~
% jupyter --version
Selected Jupyter core packages...
IPython          : 8.2.0
ipykernel        : 6.13.0
ipywidgets       : 7.7.0
jupyter_client   : 7.3.0
jupyter_core     : 4.10.0
jupyter_server   : not installed
jupyterlab       : not installed
nbclient         : 0.6.0
nbconvert        : 6.5.0
nbformat         : 5.3.0
notebook         : 6.4.11
qtconsole        : 5.3.0
traitlets        : 5.1.1
~~~

notebookがある。これさえあれば大丈夫のはず。

# Jupyter Notebookの立ち上げ方

~~~
% jupyter notebook  <任意のファイル名>.ipynb &
~~~

立ち上げたターミナルは放置。
ChromeでJupyter Notebookが起動されるはず。

# おまけ

なぜかNumPy, Matplotlib, SciPyもなくなった。。。

~~~
% pip3 install numpy
% pip3 install matplotlib
% pip3 install scipy
~~~

# Jupyter Lab

ちなみに今は[Jupyter Lab](https://jupyter.org/)を使っている。
立ち上げ方は
~~~
% jupyter lab
~~~
である。
Jupyter Notebookよりも使いやすいと感じている。
RT3050のメモリ

32Mのタイプ(16Mx2)

![写真（2022-06-28 16.24）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/a82b8e3c-fe51-3bab-70bf-a97d41781712.jpeg)

![写真（2022-06-28 16.23）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/8f2fc241-91d3-276b-69cd-0a3c1c895b54.jpeg)

16Mのタイプ

![写真（2022-06-28 16.21）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/488e6304-9295-cdd2-3fd2-b48638073386.jpeg)

![写真（2022-06-28 16.21） #2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/9e327801-ea79-f5f1-aebe-4903339563ce.jpeg)

おそらく同じ製造元で作られていて32Mの方が先に作られています。

メモリを増設したときにはu-bootを作り変えないといけません。
Nuxt 3 (RC4)  に `sb init` を使って Storybook が導入できた

現時点でStorybookはNuxt3非対応ですが、可能な限りゼロコンフィグで導入できないか色々試しました。

今回、導入に成功しましたが、ユースケースやRCのバージョン相違によっては動作しない可能性があります。

内容は、投稿時点のもので、今後変わる可能性があります。


### 大まかな手順

- Nuxt3 プロジェクトを作る
- Vue3 用の Storybook を Nuxt3 プロジェクトにインストールする（**ハマりどころあり**）

### Nuxt3 プロジェクトを作る

[Nuxt3 の Quick Start](https://v3.nuxtjs.org/getting-started/quick-start/) の手順通りに実行。

```
npx nuxi init nuxt3-storybook
cd nuxt3-storybook
yarn
yarn dev -o
```

これで `localhost:3000` を見れば Welcome ページが表示されていることを確認。
動作確認用のコンポーネントと Story を用意しておいた。

```components/Hello/Hello.vue
<template>
  <h1>hello</h1>
</template>
```

```components/Hello/index.stories.js
import Hello from './Hello.vue';

export default {
  component: Hello,
};

export const Test = () => ({
  components: { Hello },
  setup() {
    return {};
  },
  template: `
    <hello />
  `,
});
```

### Storybook を導入する

#### 1. Vue3 プロジェクトであることを `sb init` に知らせるため Vue3 をインストール → 失敗

```
yarn add -D vue@next
npx sb init
```

思惑通りそれっぽいパッケージはインストールされるが、起動しないので、 Nuxt3 インストール直後まで切り戻し。

#### 2. `sb init` のオプションで `vue3` を指定 → 1よりはマシだが失敗

https://github.com/nuxt-community/storybook/issues/330 こちらによると、 強制的にライブラリの依存系を使うことができるようです。

```
npx sb init --type vue3
```

結果は、１と同じ。切り戻し。

#### 3. Stoybook のビルダーを `vite` にする → なんかうまくいきそうだったが失敗

`sb init` で構築される設定だと Webpack 5 が使われる一方で、 Nuxt3 はデフォルトだと Vite が使われるため、不整合が発生している事がわかった。よって、 まず 2 の手順で Storybook をインストールし、ビルダーを `vite` に変えてみた。

```
yarn add -D @storybook/builder-vite
```

```.storybook/main.js
module.exports = {
  // 略
  core: {
    builder: '@storybook/builder-vite'
  }
}
```

これを追記の上、 Storybook を起動。 Storybook の画面表示まで至ったが、ずっとローディングでエラーも出ている。だいぶ近づいてきた感。１まで切り戻し。

#### 4. `sb init` 時点で `vite` を指定する → 動いた

`--type` と同様に、ビルダーも設定時点で指定できたので、指定する。

```
npx init --type vue3 --builder @storybook/builder-vite
```

Storybookが無事起動。対象 Story がデフォルトの `main.js` の設定だと読まれないので、以下の通り変更して Storybook を再起動。

```.storybook/main.js
module.exports = {
  "stories": [
    "../components/**/*.stories.@(js|jsx|ts|tsx)",
  ],
  // 以下略
}
```

できました。

#### 5. Story ファイルを TypeScript で書いてみる

脳死で `components/Hello/index.stories.js` → `components/Hello/index.stories.ts` に変更したけどちゃんと見れた。 


以上です。 Storybook の Nuxt3 正式対応が待ち遠しいですね。
herokuでgit pushした時にエラーが出てしまう。

【エラー内容】
  Processing /private/var/folders/sy/f16zz6x50xz3113nwtb9bvq00000gp/T/abs_83242e7e-f82d-4a71-8ef2-9d71d212d249gu_wxmeq/croots/recipe/certifi_1655968827803/work/certifi
remote:        ERROR: Could not install packages due to an OSError: [Errno 2] No such file or directory: '/private/var/folders/sy/f16zz6x50xz3113nwtb9bvq00000gp/T/abs_83242e7e-f82d-4a71-8ef2-9d71d212d249gu_wxmeq/croots/recipe/certifi_1655968827803/work/certifi'



【原因】
requirement-dev.txtの中でdirect URL referenceで表示されているものがあった。それが悪さして最終的にgit push heroku masterした際にエラーが出ていた。
ex)
asgiref==3.2.10
certifi @ file ~~~~~~ ←これ
dj-database-url==0.5.0


【解決方法】
pip list --format=freeze > requirements.txt
したら@ fileの記載がなくなり==3.2.3など全てversion記載になり、pushすることができるようになった。

【参考サイト】
https://stackoverflow.com/questions/62885911/pip-freeze-creates-some-weird-path-instead-of-the-package-version


https://teratail.com/questions/272968
PythonでGCP の Secret Managerのシークレットの値を取得する

# 背景

GCPのSecret Managerで設定したシークレットの値を、pythonで取得するスクリプト

# 実装

```python
from google.cloud import secretmanager


class SecretManagerUtil:

    def get_secret(self, project_id: str, secret_id: str) -> str:
        client = secretmanager.SecretManagerServiceClient()
        name = f"projects/{project_id}/secrets/{secret_id}/versions/latest"
        response = client.access_secret_version(request={"name": name})
        return response.payload.data.decode("UTF-8")

if __name__ == '__main__'
    SecretManagerUtil().get_secret(PROJECT_ID, SECRET_ID)
```

# 参考

https://cloud.google.com/secret-manager/docs/samples/secretmanager-get-secret?hl=ja#secretmanager_get_secret-python

https://cloud.google.com/secret-manager/docs/samples/secretmanager-get-secret-version?hl=ja
【令和最新版】Blogger で Markdown を用いて記事を書く方法

# 目次
- [目次](#目次)
  - [目標](#目標)
  - [やり方](#やり方)
  - [参考リンク](#参考リンク)

## 目標

Blogger の投稿ページで Markdown 記法を使えるようにする。  
この方法は Markdown 記法でブログを書き、表示する際に HTML に変換される。  

## やり方

1. Blogger の管理画面でテーマをクリック  
2. マイテーマのカスタマイズの右にある ▼ マークをクリック  
3. HTML を編集をクリック  
4. \</body\> 直前に以下のコードを追加  
   
```html
<script src='https://cdn.jsdelivr.net/npm/marked/marked.min.js'/>
<script>
  const mdEls = document.querySelectorAll('.markdown');
  for (let i in mdEls) {
    const mdEl = mdEls[i];
    const converted = document.createElement('div');
    converted.innerHTML = marked.parse(mdEl.value);
    mdEl.parentNode.replaceChild(converted, mdEl);
  }
</script>
```

Markdown でブログを書きたい場合、HTML モードでブログを記述する際に  

```html
<textarea border-style:dotted="border-style:dotted" class="markdown" disabled="disabled">

<!-- ここに Markdown 記法で記述するとプレビュー時に変換される -->

</textarea>
```

とする。 　

## 参考リンク

https://qiita.com/her0m31/items/1804bdc251a647e0e9a8  

https://www.smartbowwow.com/2021/11/blogger.html
NodejsからMySQLに接続

前回記事までで出来上がったAWS上のMySQLに、Nodejsから接続確認をしてみたいと思います。
前々回記事までで、AWS上のCentOSに、Nodejs実行環境が構築できている状態です。

## コード準備

任意のプロジェクトに以下を配置します。
const connection以下は、MySQLに設定したユーザとパスワード、データベース名をいれます。

 app.js
```
const express = require('express');
const mysql = require('mysql');
const app = express();

app.use(express.static('public'));
app.use(express.urlencoded({extended: false}));

const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'Passw0rd!',
  database: 'list_app'
});

connection.connect((err) => {
  if (err) {
    console.log('error connecting: ' + err.stack);
    return;
  }
  console.log('success');
});

app.get('/', (req, res) => {
  connection.query(
    'SELECT * FROM items',
    (error, results) => {
      console.log(results);
      res.render('hello.ejs');
    }
  );
});

app.listen(3000);
```
hellow.ejs
```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello World</title>
    <script src="/send_url.js"></script>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>
```

## プロジェクトを起動する
MySQLクライアントのアップデートをしてくださいとのエラーになりました・・・
```
# node app.js
error connecting: Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requestd by server; consider upgrading MySQL client
    at Handshake.Sequence._packetToError (/data/proj/node_modules/mysql/lib/protocol/sequences/Sequence.js:4:14)
```
調べてみるとこんな記事が。

https://www.chuken-engineer.com/entry/2020/09/04/074216

とりあえず解決させたかったので、認証プラグインの変更をしてみました。

```
mysql> SELECT user, host, plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| prog01           | %         | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)

mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Passw0rd!';
mysql> SELECT user, host, plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| prog01           | %         | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | mysql_native_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)
```

データベース接続に成功しました。

```
[root@ip-172-31-1-181 proj]# node app.js
success
```
C#開発者が学ぶJavescript勉強メモ(等価演算子と変数宣言)

# はじめに

普段C#で開発を行っていますが、最近Web開発技術も勉強中です。
その中で、C#とJavascriptで概念が違って混乱したことがあったので整理します。

# ==と===

C#では、値が等しいかどうかに==を使います。値型であれば、単純に値同士に比較をしてくれますし、参照型であればインスタンスが同じであるかで比較してくれます。
しかし、Javascriptでの==は意味が違うようでした。
例えば、以下のような場合、trueが返ってきます。

```js
var a = "1";
var b = 1;

console.log(a==b);
結果：true
```
今見ても不思議な感じがしてしまいますが、文字列の1と数値の1は等しいとみなされるようです。

> 等価演算子 (==) は、二つのオペランドが等しいことを検査し、論理値で結果を返します。厳密等価演算子とは異なり、オペランドの型が異なる場合には型の変換を試みてから比較を行います。
> 数値と文字列を比較する場合、文字列を数値に変換しようとします。

とリファレンスにありました。ほかにもnullとundefinedの比較はtrue、オブジェクトと数値または文字列の比較の場合、オブジェクトを値型に変換して比較しようとするみたいです。詳しくは[こちら](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Equality)。

Javascriptでの==は同じ型に変換を行ってから比較する場合があるため、意図せずtrueになってしまいバグを埋め込んでしまいそうです。
===で比較をすれば、型変換は起きず、数値の1と文字列の1を違うものとみなしてくれます。
C#の==と同じ感覚で使うのであれば、===を使った方がよさそうだとわかりました。

# varとlet

C#では、変数を置く際にvarをよく使いますが、JavascriptのvarはC#とは異なる挙動をするようです。
varで同じ変数名で再度宣言することが可能で、しかも、それは同じ変数として扱われます。C#の場合、同じ変数名を使用すると構文エラーになりますが、Javascriptは大丈夫なようです。

また、Javascriptでは変数の巻き上げというのが起こり、varの場合、グローバルにあるいは関数内に定義していればその変数を定義より前で使うことができるようです。(関数内での宣言であれば関数内のみで使用可能。)
ただし、初期化は巻き上げられないため、初期化前にアクセスすると、varの場合はundefinedが返ってきます。
varで宣言した時点でundefinedで初期化されると考えてもいいのか(?)と思っています。

```js
console.log(x);   　// undefined 変数の定義の巻き上げが起こるのでエラーにはならないが、
                    // 初期化は巻き上げられない。
var x = 1;
console.log(x);     // 1
console.log(y);     // ReferenceError yは関数の中なので、外から参照できない。

function foo() {
  var y = 2; 
  console.log(y);   // 2
  console.log(x);   // undefined 下で宣言しているので巻き上げがおこる。(グローバル変数でなく関数内のローカル変数を参照する) 未初期化のため undefined となる。
  var x = 3         // 最初に宣言したxと同じ変数として扱われる。
}

foo();
console.log(x)      // 3。関数の中でvarと宣言しなおしても変数名が同じであれば同じ変数扱いになる。　　
```

Javascriptではvarの他にletやconstでも変数を宣言できます。constは一回だけ宣言、代入ができる変数で、そこまでややこしくないので割愛します。
letは、変数の有効範囲がブロックの中のみという点がvarと異なります。

```js
function varTest() {
  var x = 1;
  {
    var x = 2;       // 同じ変数
    console.log(x);  // 2
  }
  console.log(x);    // 2
}

function letTest() {
  let x = 1;
  {
    console.log(x);  // ReferenceError letも変数の定義の巻き上げが起こる。 
                     // また、同じ変数名であるがブロックの中で再度宣言されており、ブロックの外とは異なる変数扱いとなる。
                     // しかし、letの場合はundefinedで初期化されないためエラーとなる。
    let x = 2;       // 異なる変数として宣言される。
    console.log(x);  // 2
  }
  console.log(x);    // 1。{}(ブロック)の中と外では、同じ変数名を宣言していても、異なる変数として扱われる。
}
```

varは再宣言が可能なので、意図せず同じ変数名を使った場合に気が付けなさそうだと思いました。
letはブロックが異なれば、同じ変数名を使えはしますが異なる変数として扱えるので意図せず値を代入することは無さそうです。
C#と同じ感覚で使えそうなのはletでしょうか。varだと再宣言できる点がミスにつながりそうで怖いです。
巻き上げがあるという意味ではどちらもC#に無い概念ですが、letであればエラーになるため、まだわかりやすそうです。

# さいごに

C#しか知らないので、慣れるまでは混乱して間違えそうだと思いました。
特にvarとletは記事にまとめてみようとすると、すごく混乱してしまいました。わかったようでわかってなかったなと思いました。
間違えてそうなので教えてもらえるとありがたいです。
AWS LambdaでSeleniumを動かすときの注意点

# 概要

* ある日、seleniumによるフロント画面の正常性確認を行うAWS Lambdaの実行エラーが頻発していることに気づき調査することになりました。
* その際に気づいたseleniumの特性とAWS Lambdaの特性について今回は記事にしていこうと思います。
* もし同じような現象に陥った人がいた時の何らかの助けになれば幸いです。

## 仕様の確認

* フロント画面の正常性を確認するためにseleniumのwebdriverでヘッドレスモード実行をしていました。
* 実行には、CloudWatchEventを利用し、５分おきにこのLambdaを発火し、実行結果をCloudWatchLogsに吐き出すようになっています。

## 何が起きたのか

* 一定の間隔でこのseleniumを動かすLambdaが実行中にエラーとなり落ちていました。
* ただ毎回の実行で、このLambdaが落ちるというわけではなくたまに実行エラーとなるのがとても不思議でした。

### Lambdaでの実行エラーが発生したときの調査方法

* Lambdaのインサイトメトリクスを有効にするとLambdaのリソースの変化をCloudWatchから追うことができます。
* 今回のようなケースを再現すると下記のようなエラーの間隔とメモリ、CPUの使用率を示します。

![スクリーンショット 2022-06-28 15.02.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/a05488f2-bd83-3560-9fab-f9fb876a0853.png)

* また、下記がその時の実行ごとのメモリ使用率を示したものなのですが、徐々にメモリ使用率が上がっていっていることがわかります。
![スクリーンショット 2022-06-28 15.10.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/ec4ab271-9482-1e06-28b1-49bdc5b5745e.png)


## 原因とLambdaとSeleniumの特性

* 今回の原因は、実はLambdaとSeleniumの特性が非常に良く現れた現象と言えます。
* 実は、AWS Lambdaは、ある短期間で実行されると前回の実行環境を再利用するという特徴があります。
※ 詳しくは以下の記事を参照ください。

https://qiita.com/yoshii0110/items/18c15f7fd14ec18f8ad6


* 今回、メモリが徐々に上昇し、メモリがサチるとリセットされるという動作は、再利用されたコンテナ内でメモリ不足が発生すると、Lambdaが自動的にコンテナの再作成を行う為です。

**では、なぜ再利用されたコンテナ内でメモリが急上昇したのか？**

* それは、Seleniumの特性にあります。
* 実は今回の実装コード内でSeleniumで利用しているwebdriverのプロセスをきちんと切っていないため、毎回の実行で同一コンテナ内でプロセスを作成し、テストをしていることで前のプロセスが残りメモリを食い潰したというのが原因になります。

### Seleniumの実行を終了させるメソッド

* **driver.close()： アクティブになっているタブを終了**
  ただ、「driver.close()」だけだとプロセスが残り続ける可能性があります。

* **driver.quit()： すべてのタブを閉じてブラウザを終了**
  「quit()」でプロセスを完全に終了させることができます。

=> **なので、Seleniumの実装ではテストが完了しSeleniumを終了させる場合は、driver.quit()：を使うのが良いでしょう。**

* 今回のエラーについても、driver.close()：からdriver.quit()：に変更したことでLambdaの実行エラーがなくなりました。

# まとめ

* もしLambdaを使用し同じような現象に陥っていた場合は、一度Lambdaのインサイトメトリクスを有効化しリソースがどう使われているのかを確認するとよいでしょう。

# 参考

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Lambda-Insights-metrics.html
【Rails】Railsのform_withでリセットボタンを設定

## はじめに 
Rails の`form_with`を使用して検索フォームを実装するにあたり、リセットボタンの実装方法について調べました。
  
HTMLでは`input`タグで`type="reset"`を指定すれば簡単にリセットボタンを作成できます。
```html
<form>
  <input type="reset" value="リセット">
</form>
``` 
`form_with`でも`type属性`に`reset`を設定できるのでしょうか。
  
## 使用環境
- Ruby 2.7
- Rails 6.1
- Bootstrap 4.0
  
## type="reset"を生成するヘルパーはなさそう
`form_with`では様々なフォーム要素を生成するヘルパーメソッドがあります。
(例)
```erb
<%= form.text_field :title %>
<%= form.check_box :pet_dog %>
<%= form.radio_button :age, "child" %>
<%= form.text_area :message, size: "70x5" %>
<%= form.hidden_field :parent_id, value: "foo" %>
<%= form.password_field :password %>
<%= form.number_field :price, in: 1.0..20.0, step: 0.5 %>
<%= form.range_field :discount, in: 1..100 %>
<%= form.date_field :born_on %>
<%= form.time_field :started_at %>
<%= form.datetime_local_field :graduation_day %>
<%= form.month_field :birthday_month %>
<%= form.week_field :birthday_week %>
<%= form.search_field :name %>
<%= form.email_field :address %>
<%= form.telephone_field :phone %>
<%= form.url_field :homepage %>
<%= form.color_field :favorite_color %>
```
  
送信ボタンを生成は`form.submit`があります。
（class には Bootstrap を使用しています。）
```erb
<%= form.submit "検索する", class: 'btn btn-info btn-block my-3' %>

#=> HTML出力
<input type="submit" name="commit" value="検索する"　class="btn btn-info btn-block my-3" data-disable-with="検索する">
```
この送信ボタンの`type属性`が`reset`で生成できるヘルパーを調べて見たのですが、見つかりませんでした。（`form.reset`のように定義して生成できればよかったのですが...。）
  
参考 :　[Railsガイド](https://railsguides.jp/form_helpers.html#:~:text=%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%EF%BC%89%E3%80%82-,1.2%20%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E8%A6%81%E7%B4%A0%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B%E3%83%98%E3%83%AB%E3%83%91%E3%83%BC,-form_with%E3%81%A7%E7%94%9F%E6%88%90)

## 解決策  
### 1. `jQuery`の`.reset()`を使うと簡単に生成できる
入力した値を**初期値**にリセットする
  
（注）`reset()`を使用する場合、あらかじめ値が入力されているフォームはその値に戻るため、フォームが`空`にはなりません。  
`初期値が空の状態`のフォームに値を入力して、やっぱり「リセットしたい！」という時にリセットボタンを押下すると`初期値の空の状態`に戻ります。
  
**HTML出力**
```html
<form id="post_search">
  <label for="q_user_name_or_content_cont">キーワード</label>
  <input type="search" id="q_user_name_or_content_cont">
</form>

<button type="button" id="reset-button">リセット</button>
```
**iQuery**
```js
$(function(){
  $('#reset-button').on('click', function(){
    $('#post_search')[0].reset();
  });
});
```
これで`id="post_search"`を持つフォームのフィールドの値が**一括リセット**されます。
  
### 2. `jQuery`の`val('')`を使用して、空にする
リセットボタンを押下した場合に、フォームに`空`の値を挿入する
**HTML出力**
```html
<form id="post_search">
  <label for="q_user_name_or_content_cont">キーワード</label>
  <input type="search" id="q_user_name_or_content_cont">
</form>

<button type="button" id="reset-button">リセット</button>
```
**iQuery**
```js
$(function(){
  $('#reset-button').on('click', function(){
    $('input[type="search"]').val('');
  });
});
```
これで`input[type="search"]`を持つフォームのフィールドが**空**になります。
  
## まとめ
僕の実装の場合は検索ボタン押下後ページ遷移しても検索フォームにキーワードを残しているので、フィールドの`value`に値が挿入されている状態になっています。そのため`val('')`として`空`を挿入しました。
  
リセットボタンで`初期値に戻したい場合` => `reser()`
リセットボタンで`フォームの値を空にしたい` => `val('')`

のような使い方で良いのかな？と思います。
CentOS steam 8にMySQLをインストールして初期設定する


昨日の投稿の続きで、
MySQLを導入して初期設定をしたあとNodejsから接続確認をします。


## MySQLインストール
### 1. yumリポジトリの追加
MySQLはyumコマンドでインストールします。
CentOS 7では公式のyumリポジトリにMySQLがないので、まずはMySQLの[公式](https://dev.mysql.com/downloads/repo/yum/)が用意しているリポジトリを追加します。


```
# yum localinstall http://dev.mysql.com/get/mysql80-community-release-el8-4.noarch.rpm
```
/etc/yum.repos.d配下にmysqlのリポジトリが追加されていることが確認できます。
```
# ls /etc/yum.repos.d
centos-addons.repo  mysql-community-debuginfo.repo  mysql-community-source.repo
centos.repo         mysql-community.repo
```
### 2. yumでのMySQLインストール
インストールします。yumコマンド実行後”Complete!”と表示されればOK。
```
# yum install -y mysql-community-server
```

### 3. MySQLインストール確認、起動、停止
バージョン確認でコマンドが実行できるか確認
```
# mysqld --version
/usr/sbin/mysqld  Ver 8.0.29 for Linux on x86_64 (MySQL Community Server - GPL)
```

起動
```
# systemctl start mysqld
```
停止
```
# systemctl stop mysqld
```
自動起動設定
```
# systemctl enable mysqld
```

## MySQL初期設定

### 1. MySQL ユーザ初期パスワード変更
まずは、初期パスワードの確認です。
初期パスワードは、mysqlのログの中で確認できます。ログの中身をrootでgrepした時の一番最初の行に記載されています。ログファイルは/var/log/mysqld.logです。
```
# cat /var/log/mysqld.log | grep root
2022-06-27T21:20:21.135654Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: V?BPS_=+k8J8

# mysql -u root -p 
Enter password: （上記パスワードを入力しログイン）
```

初期パスワードを変更します。
```
mysql> SET PASSWORD = 'Passw0rd!';
Query OK, 0 rows affected (0.00 sec)
mysql> \q
Bye
#
# mysql -u root -p
Enter password:
mysql>
```


## データベース、テーブル作成、データ投入
簡単なデータ投入までやりたいと思います。

### 1. データベース作成

データベース作成します。
```
mysql> create database list_app;
Query OK, 1 row affected (0.01 sec)
```
USEデータベースで使用するデータベースを選択
```
mysql> use list_app;
Database changed
```
### 2. テーブル作成
テーブル作成します。
```
mysql> create table items(id INT,name TEXT);
Query OK, 0 rows affected (0.03 sec)

mysql> SHOW tables;
+--------------------+
| Tables_in_list_app |
+--------------------+
| items              |
+--------------------+
1 row in set (0.00 sec)

```
### 3. データ投入
データ投入します。
```
mysql> INSERT INTO items(id,name) values(1,'じゃがいも');
mysql> INSERT INTO items(id,name) values(2,'にんじん');
mysql> INSERT INTO items(id,name) values(3,'たまねぎ');

mysql> select * from items;
+------+-----------------+
| id   | name            |
+------+-----------------+
|    1 | じゃがいも      |
|    2 | にんじん        |
|    3 | たまねぎ        |
+------+-----------------+
3 rows in set (0.00 sec)
```

データ投入までできたので、
このあとNodejsからデータベース接続していきたいと思います。


本件、以下参考にさせていただきました！ありがとうございます！
https://qiita.com/nooboolean/items/7efc5c35b2e95637d8c1
インプットした後のロードマップの作成

ある程度、独学やスクールで学習したみなさん！
次のステップとして自作のアプリの作成や転職を考えている方、、、

一度、自分が学習したことをまとめてみませんか？
その時にオススメしたい方法がこちら！

いや。ホンマに効果あるん？
絶対、読んでもスルーするやつやわー。
まぁ。そういわずに、凡人の戯言だと思って聞いてくださいな・・・

>マイロードマップの作り方

まず、手順としては

１フローチャートの作成
２自分のロードを作成
３ゴールの作成
4 自分のロードとゴールを線で結ぶ。
5 ゴールに必要なものが足りない場合、新らたにロードを作成する

#### 1 フローチャートの作成

オススメの作成ツールは
draw.io 
(公式サイト：https://app.diagrams.net/ ）
Googleのアカウントが有れば、無料から使える！

上の「create new ・・・」を選択して、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314502/aacff8db-e69c-0596-46ed-5ac1bbd425e6.png)

目的に合ったフォームを選択して、「Create」をクリック
（今回は何もない状態から始める Blank Diagramを選択)
 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314502/acec29fd-6dc3-f9c3-13f5-0742d6715767.png)

>自分のロードを作成

1ブロック学習した言語と学習に使った教材（あればで良い）ここは自分でカスタマイズ！

（例）
HTML・CSSとJavaScriptを勉強して、アウトプットにwebサイトを作成した場合、以下の図のようになる。
（※インプットは左に、アウトプットは右に、上から時系列順になりようにしてますー）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314502/4577f05c-9f9a-b97c-1db9-ebe7dae2fb72.png)

#### ３ゴールの作成

次にゴールの作成をしていきます。
例えばゴールとは・・・
・自作webサイト作成
・案件獲得
・記事作成
などなど

そのゴールに必要な言語や知識を細分化して小さなブロックとして作成。
下にゴールの簡単な概要を作成。（ザックリとでいいので概要と必要な処理などを記載）

（例）
今回はwebサイトを作成をゴールにします、
（ゴールは横に作成致します）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314502/802937ef-2a54-bf7e-490c-0354bd973c83.png)

ゴールに必要な知識は縦に並べて、習得したマイロードに対応させておきます。

#### 4 自分のロードとゴールを線で結ぶ。

対応しているロードブロックとゴールブロックを線で線でつなぐ。（正気これはどっちでもよい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314502/9118b182-d952-1910-0d9e-20d82b5353fa.png)


#### 5 ゴールに必要なものが足りない場合、新らたにロードを作成する
この時、気づくのがゴールに必要な知識がまだロードマップにないので、あらたにロードに追加させます。


必要なブロックは色をオレンジにしときましょう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1314502/1fb9c7ea-81e4-2841-9df2-7f1ef262389f.png)

こうすることで、新たなマイロードが更新されました！

##### まとめ

このように、自分でロードマップを作成し、ゴールを掲げることで自分が今なにができるのか、ゴールに必要なものは何か、今何が必要なのかを知ることができます。
今回行ったものは基本中の基本になります。

以下の様に拡張が可能です。
・ロードを細分化して、明確にさせる。
・ロードに日付を付けて、いつ習得したかをわかるようにする。
・ロードを何週したかわかるようにする。

<b>何かを習得したら、マイロードを更新し、常に、ゴールを意識して、学習しましょう！</b>
【Xcode】Playgroundの開き方

# 方法
Xcodeを起動します
メニューバーの「File」を選択します。
![スクリーンショット 2022-06-28 14.53.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/844411fc-82e6-93f1-5e60-561356d5a262.png)

「New」を選択して、「Playground」を選択します。
![スクリーンショット 2022-06-28 14.56.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/f292d203-5f01-4877-5b2d-6953b732d6d7.png)

「Blank」を選択して、「Next」を選択します。
![スクリーンショット 2022-06-28 14.59.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/3d75533d-663f-93fa-c8fa-0f034d7aad3a.png)

ファイル名と保存場所を選択して「Create」を選択します。
![スクリーンショット 2022-06-28 15.01.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/636fbb10-1af9-2928-4ba1-613ef2d2ccf0.png)

Playgroundを開くことができました。
![スクリーンショット 2022-06-28 15.01.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/a8dc78d5-b094-9bf1-5ba6-bd42ecf7616b.png)
AとBの日付の差分がｎ日以上ある場合、エラーになるValidationを作る。

## 概要
AとBの日付の差がｎ日以上ある場合、
エラーになるようValidationを作成する。

例：AとBの日付の差が10日以上ある場合、エラーになる。

　例１：
　　A（4/1）
　　B（4/16）
　　→15日差分がある。
　　　→エラー。

　例２：
　　A（12/30）
　　B（12/21）
　　→9日差分がある。
　　　→OK


## 日付の差分を求める
下記の書き方で日付の差分を求めてみた。

```rb
hogehoge_on = "2022/04/01".to_date
piyopiyo_on = "2022/04/08".to_date

# hogehoge_on からpiyopiyo_onまでの日付の差
(hogehoge_on - piyopiyo_on).to_i.abs
# => 7

# ※to_iを入れないとよくわからない結果が出力される。
(piyopiyo_on - hogehoge_on)
# => 7/1

```
参考：

https://style.potepan.com/articles/27153.html#-2

https://qiita.com/mat827/items/659e6e4a2ad83d8c03e1



## Validateを作成する。

```models/hogehoge.rb

class HogeHoge < ApplicationRecord
   validate :check_date_diff

   private
   def check_date_diff
　　 # hogehoge_onとpiyopiyo_onのどちらか空の時はバリデーションを実行しない
     return true if (self.hogehoge_on.blank? || self.piyopiyo_on.blank?)
     
     if (self.hogehoge_on - self.piyopiyo_on).to_i.abs > 9
       errors.add(:base, "hogehoge日とpiyopiyo日の差分は9日以内でお願いします")
     end
     
   end
end

```

### 終。
2分で分かるDocker～コンテナ入門～

# コンテナ入門

* 仮想マシンはハイパーバイザー上に仮想マシンが作成されます。
![Docker - 02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/26bbdb75-abf1-17b5-2d24-1a0c30d79a6f.jpeg)

* コンテナではOS（カーネル）は共有されます。Dockerはコンテナを管理するソフトです。
![Docker - 03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/51e68791-a147-cb97-de27-009fc4afe37b.jpeg)

* カーネルは共有されますがディストリビューションはコンテナに含まれます。
![Docker - 04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/8faaabdc-a42b-fcc8-e4ca-3a3b83879912.jpeg)

* コンテナはイメージから作成します。
![Docker - 05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/cdb7b52d-c6d0-2b37-3400-5823cb3d2e4d.jpeg)

* イメージはリポジトリから取得したり自分で作成します。
![Docker - 06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/f82c1c9a-4108-9d9a-e977-c6e9db0c5633.jpeg)

* コンテナは使い捨てのため、データはOS側に保存します。
![Docker - 08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/19d94ab1-5c74-85ac-32a1-54e4c19e10e9.jpeg)

* ポートマッピングによりコンテナにアクセス出来ます。
![Docker - 09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/94cf9941-6a03-09dd-58fa-6d159eb02cb3.jpeg)

* docker runコマンドでイメージをダウンロードしてコンテナを起動出来ます。
![Docker - 10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/3a095c04-219c-dbbc-73d6-26bc716ce415.jpeg)

* 複数のコンテナ設定はDocker Composeで管理出来ます。
![Docker - 11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/4ff2dd1e-2c5e-3283-b6b3-48ccbe1b5022.jpeg)

* コンテナの特徴は下記になります。
![Docker - 12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/6bb62dd5-3f3c-0695-ed0f-8fc84cd906c5.jpeg)
M5Paper: Noto_Sans_JP フォントを使う

次のフォントファイルをダウンロードします。

```text
Noto_Sans_JP.zip
```

解凍して出来た次のファイルを使います。

```text
NotoSansJP-Regular.otf
```

このファイルを ttf に変換します。
変換は、 Ubuntu 22.04 で、fontforge を使いました。
fontforge の使い方はこちら
[FontForgeで OTF形式のフォントファイルを TTF形式に変換する方法](http://www.neko.ne.jp/~freewing/software/fontforge_convert_otf_font_to_ttf_format/)

変換結果

```text
4548208  1月 29  2015 NotoSansJP-Regular.otf
4968020  6月 28 13:23 NotoSansJP-Regular.ttf
```

NotoSansJP-Regular.ttf を font.ttf にリメームして、
fat32 で初期化した SD に書き込みます。

M5Paper のプログラム

```ino:ttf_sd.ino
// ---------------------------------------------------------------
//	ttf_sd.ino
//
//				Jun/28/2022
// ---------------------------------------------------------------
#include <M5EPD.h>
#include <FS.h>

#define USE_SD

M5EPD_Canvas canvas(&M5.EPD);

// ---------------------------------------------------------------
void setup() {
	M5.begin();
	M5.TP.SetRotation(90);
	M5.EPD.SetRotation(90);
	M5.EPD.Clear(true);
Serial.print ("*** setup ***\r\n");
Serial.print ("*** Jun/28/2022 PM 14:00 ***\r\n");
 	

	canvas.createCanvas(540, 960);
	canvas.setTextDatum(TC_DATUM);
	canvas.setTextSize(3);

	canvas.drawString("... Initializing ...", 270, 640);
	canvas.pushCanvas(0,0,UPDATE_MODE_A2);

	canvas.drawString("Loading font ...", 270, 230);
	canvas.pushCanvas(0,0,UPDATE_MODE_A2);

	Serial.print ("*** bbb ***\r\n");
	canvas.loadFont("/font.ttf", SD);
	Serial.print ("*** ccc ***\r\n");
 
	canvas.createRender(96, 256);
	canvas.createRender(40, 256);
	Serial.print ("*** ddd ***\r\n");

	canvas.drawString("OK!", 270, 254);
	canvas.pushCanvas(0,0,UPDATE_MODE_A2);
Serial.print ("*** eee ***\r\n");


	// 時計を描画
//	M5.EPD.Clear(true);
}

// ---------------------------------------------------------------
void loop() {
	draw_proc();
	delay(5000);
	Serial.print("*** loop ***\r\n");
}

// ---------------------------------------------------------------
void draw_proc() {

	canvas.setTextDatum(TL_DATUM);
	canvas.fillCanvas(0);
	canvas.drawLine(0, 80, 540, 80, 2, 15);

	String arraya[] = {"ブレーメンの音楽隊","白雪姫","あかずきん",
			"ヘンデルとグレーテル","おおかみと七匹のこやぎ",
			"灰かぶり","親指こぞう","三枚の鳥の羽",
		"AAAA","BBBB","CCCC","DDDD","EEEE","FFFF","IIII","JJJJ"};
int xpos = 50;
	canvas.setTextSize(40);

	for (short it=0; it< 16; it++)
		{	
		canvas.drawString(arraya[it], xpos, 100 + 50 *  it);
		}

// canvas.pushCanvas(0,0,UPDATE_MODE_DU4);
	
	 canvas.pushCanvas(0,0,UPDATE_MODE_A2);

}

// ---------------------------------------------------------------
```

Arduino IDE
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/4b20860d-89cc-0666-d32f-dea08c67e957.png)


SD を挿入して実行した結果
![IMG_20220628_142600.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/4fe2ac45-b0fb-d122-9100-bebe52dc6b8c.jpeg)
WinMerge で 比較結果のフィルタリングを実現する

## やりたいこと

* WinMerge で、フォルダを比較した結果から、特定のファイル名やフォルダ名でフィルタリングしたい

## 解決した方法


### フィルターファイルの準備

* 任意のファイル名で xxxx.flt ファイルを、`Documentsディレクトリ` 配下に配置する。
    * `ドキュメント ディレクトリ` 以下に配置する理由としては、そこに配置するとデフォルトでWinMerge上から読み込まれるから。
* 下記ファイルのように `name:`、`desc:`、`def:`、`f:`、`d:` を定義する。
* `f:` はファイル、`d:` はディレクトリに一致させたいパターンを定義する（正規表現使用可）
* 「`d:` に一致する、`f:` のみを表示」（もしくは除外）のようなことが出来る。
    * `def:` に設定する値は下記（直観とは逆だったりする）
        * **のみ表示したい**場合は、exclude
        * **以外を表示したい**場合は、include

```flt:xxxxx.flt
## This is a directory/file filter template for WinMerge
name: xxxx
desc: search xxxx
## Select if filter is inclusive or exclusive
## Inclusive (loose) filter lets through all items not matching rules
## Exclusive filter lets through only items that match to rule
## include or exclude
def: exclude
## Filters for filenames begin with f:
## Filters for directories begin with d:
## (Inline comments begin with " ##" and extend to the end of the line)
f: xxxx$ ## Filter for filename
d: \\*$ ## Filter for directory
```

### フィルターファイルを適用した上で比較を実行

* ディレクトリ同士を比較する際のUI（１番目のファイルまたはフォルダーとかが書いてあるUI）の左下に「フォルダー: フィルター」という欄があるので、そこで `flt ファイル` を指定してください。
    * デフォルトでは「`*.*`」（＝全て）になっております。
* サブフォルダーを含める場合は、☑を有効にしてください。


##### 検索用キーワード

* WinMerge、ウィンマージ、うぃんまーじ
* Filtering、filter、正規表現、Regex
【MT7】フォルダのベースネームにアンダーバーを使用すると、ハイフンに変換される場合の対処法

## はじめに
#### MovableType7
・プライバシーポリシー（ベースネームは **privacy_policy** ）というフォルダを作成。
・ウェブページの作成でプライバシーポリシーのフォルダを選択すると、ディレクトリが **privacy-policy** になってしまった。
　↓↓
<font color="DarkBlue">フォルダ名にアンダーバーを使用しても、ハイフンに変換されないようにしたい。</font>


## フォルダの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104075/7e13f695-d7eb-5d5b-5694-87058c94f3d3.png)


## ウェブページ登録画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104075/37f51a26-71cb-2b31-489e-32359bac25d8.png)
プライバシーポリシーのウェブページを作成するため、フォルダを選択。

　↓↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104075/6548a818-d4ff-0c85-d46d-3d28788988c0.png)
URLが「privacy<font color="Red">**-**</font>policy」になってしまう。

## 解決方法（アーカイブパスの変更）
### 修正前

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104075/e649909b-9b50-5683-fd56-a5a8d1da38f3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104075/cd16deb7-290b-d8da-40ff-047aca9e8868.png)

アーカイブパスが　**folder-path/page-basename.html** となっています。


### 修正後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104075/3a8f2b8d-9cd9-931c-74d9-37aa524dc4a4.png)
カスタムをクリックし、アーカイブパスを <font color="Red">**%c/%f**</font> に変更。
※ **%-c/%-f**にすると、「privacy<font color="Red">**_**</font>policy」→「privacy<font color="Red">**-**</font>policy」に変わってしまうので注意。


#### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1104075/4860ad0d-9f79-9d3b-4363-d5ab42264062.png)



## 参考サイト
・[アーカイブマッピングで利用するアーカイブファイル名の定義  | MovableType公式リファレンス](https://www.movabletype.jp/documentation/appendices/archive-file-path-specifiers.html)


・[出力ファイル名のアンダースコアがハイフンに変換されてしまう  | MovableType公式 Q&A](https://www.movabletype.jp/faq/converted-underscore-to-hyphen.html)
EC-CUBE＋Docker Compose　環境構築手順

# 検証環境

* Windows 10 Pro
* Docker Desktop for Windows

# GitHubからリポジトリをClone

Windows環境でGit Cloneすると、ファイルの改行コードがWindows標準のCRLFになってしまい、
起動時にstandard_init_linux.go:211: exec user process caused "no such file or directory"というエラーが発生してしまいます。
Linux環境でリポジトリをCloneすることにより回避できます。

## Windows PowerShellよりwslを起動します

```PowerShell:PowerShell
wsl
```

## リポジトリを作成するディレクトリへ移動します
以下の例では、dockerディレクトリ
```PowerShell:PowerShell
cd docker
```

## GitHubへアクセスし、リポジトリのURLを取得します
EC-CUBEのサイトよりGitHubを確認します

https://doc4.ec-cube.net/quickstart/install

https://github.com/EC-CUBE/ec-cube

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1393249/d0494b6e-028a-3e8c-e86d-058cff7d984a.png)

## クローンします
取得したリポジトリURLを指定して、クローンします

```PowerShell:PowerShell
git clone https://github.com/EC-CUBE/ec-cube.git
```

# コンテナを起動します

```PowerShell:PowerShell
docker-compose up -d
```
# 初回はインストールスクリプトを実行します

```PowerShell:PowerShell
docker-compose exec -u www-data ec-cube bin/console eccube:install -n
```

# MySQL
docker-compose.mysql.yml を指定します。

```PowerShell:PowerShell
docker-compose -f docker-compose.yml -f docker-compose.mysql.yml up -d
```

# データベーススキーマを初期化
スキーマ作成と初期データ投入を行います。
```PowerShell:PowerShell
docker-compose -f docker-compose.yml -f docker-compose.mysql.yml exec ec-cube composer run-script compile
```

# ブラウザよりアクセスする
以下のURLにアクセスする。

http://localhost:8080
PowerApps入门教程

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280122/d6261656-67d6-7037-3a26-4e28a9275240.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280122/5e978eb7-576f-4b2a-2c12-ceaa6ca85f8a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280122/44f6b3ea-4baf-6ef6-da06-032dcb8ed434.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280122/09bd4542-7e9e-9c0e-62be-88f78341b732.png)
--------------------------------------------------------------------------------------------------------------------------

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280122/30abcd11-05bd-494f-cc47-bcc316015de0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280122/151d6acf-7db8-4572-4c18-2a44e128d333.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280122/bedb8751-853e-b36a-38b9-9d1932809518.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280122/1fb4215c-d2dc-e5c6-c118-44e7b1d58e80.png)
Bakeコマンドでスピーディーな開発へ

## はじめに
今回はCakePHPのbakeコマンドについて
紹介していこうと思います。

## Bakeコマンドとは
bakeとは、CakePHPのMVCモデルによる
**Webアプリケーションの雛形を自動生成**するための機能です。
CUI（コマンド）のツールでコマンドで打つことで実行が可能です。

## 必要なもの
テーブルデータを元に自動生成するものがあるため、
最初にテーブルを作成させましょう。

## Bakeコマンドで作れるもの
:::note warn
警告
Windows システムの場合は
下記のコマンドを入力する際に、`bin\cake bake`で入力してださい。
:::
#### ・コントローラー
コントローラーは`controller ＋ コントローラー名`で生成できます。
```
$ bin/cake bake controller Articles
```
テストコードが不要な場合は、**--no-test** オプションをつけましょう。

#### ・モデル
モデルは`Model＋ テーブル名`で生成できます。

:::note warn
警告
指定したテーブル名が作成されていない場合はエラーとなります。
:::

```
$ bin/cake bake model Articles
```
テストコードが不要な場合は、**--no-test** オプションをつけましょう。

#### ・テンプレート
テンプレートは`template ＋ テンプレート名`で生成できます。

:::note warn
警告
指定したテンプレート名のテーブルが作成されていない場合はエラーとなります。
:::
```
$ bin/cake bake template Articles
```
指定したファイルを生成する場合
```
$ bin/cake bake template Articles add
```

#### ・コンポーネント
コンポーネントは`component ＋ コンポーネント名`で生成できます。
```
$ bin/cake bake component Sample
```
テストコードが不要な場合は、**--no-test** オプションをつけましょう。

#### ・ヘルパー
ヘルパーは`helper ＋ ヘルパー名`で生成できます。
```
$ bin/cake bake helper Sample
```

#### ・ビヘイビア
ビヘイビアは`behavior＋ ビヘイビア名`で生成できます。
```
$ bin/cake bake behavior Sample
```

## 最後に
新規作成するときに既存のファイルをコピペして作成する場合があると思いますが
こちらのコマンドで作った方がスピードは断然早く、テストコードのクラスまで
作成してくれるのがとても便利ですね。

## 参考
https://book.cakephp.org/bake/1/ja/usage.html#id1