OmniAICreator/Qiita-1.07M huggingface dataset:
【データモデル】テーブルJOINを定義してみる

Sharperlightは、基のデータベースではなく、Sharperlightのデータモデル層にクエリに必要なJOINを作成することができます。
:bulb: **基のデータベースには一切変更の必要はありません。**

このような例があるとします。Sales(売上)テーブルには、製品IDが存在するがProducts(製品)テーブルへのJOINが存在しないため、製品の詳細が取得できません。
![2022-03-02 Figure 01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/9a3fb062-0901-8a41-c77b-8255888468ee.png)
そこで、このSharperlightの製品"Qiita Demo Product" の[データモデル](https://qiita.com/Miki_Yokohata/items/f7973bbc0e9fc65a7416)を更新し、Sales(売上)テーブルにProducts(製品)テーブルへのJOINを追加してみます。
Sharperlightアプリケーションメニューから”スタジオ”を選択します。
![2022-03-02 Figure 02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/03dacdc7-3a50-640a-2328-2308bf2611ad.png)
スタジオが起動したら、"Qiita Demo Product"データモデルのファイルを選択します。
![2022-03-02 Figure 03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/90e002ea-b107-820f-9192-8f0ffc15453d.png)
次にTablesタブ、Salesテーブルの選択、 Salesテーブルをダブルクリックでその詳細を中央の枠に表示します。
![2022-03-02 Figure 04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/e12cf604-4d97-de55-c715-8a49b1294388.png)
[製品Id]フィールドを選択し、右クリックメニューを表示します。そして"New Join"を選択します。
![2022-03-02 Figure 05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/d94050f6-ce3e-a64a-3376-834212677e15.png)
JOIN先のテーブルを選択します。ここではProducts(製品)テーブルですね。
![2022-03-02 Figure 06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/e4fe5e84-c828-ba16-9d5c-eb9670daba1e.png)
Sales(売上)テーブルへのJOINを定義するダイアログが表示されます。上部左側がSales(売上)テーブル、つまり接続元、上部右側がProducts(製品)テーブル、接続先です。
JOINを作成する対象フィールドをそれぞれのテーブルから選択します(1)と(2)。
LEFT OUTER JOINが生成されるので、Add(追加)ボタンで決定します。
JOIN句を確認したらOKボタンを押して完了します。
![2022-03-02 Figure 07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/084a806f-ca48-0578-0f68-8fb2fd8b1b3c.png)
Sales(売上)テーブルにProducts(製品)テーブルへのJOINが作成されました。
![2022-03-02 Figure 08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6ccbf3d0-1253-f574-d9ad-da7cfbf5e18c.png)
データモデルを保存します。
![2022-03-02 Figure 09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6553465e-4b84-15c4-c0a5-6d4da5d2f19a.png)
Sharperlightアプリケーションメニューからクエリビルダを再起動します。既にクエリビルダが起動している場合は一度閉じてから再起動します。そうすることでデータモデルへの変更が有効になります。
Sharperlightの製品には"Qiita Demo Product"、テーブルはSales(売上)を選択します。”選択”階層表示領域には、フィールドと共に先ほど追加したProducts(製品)テーブルへのJOINが表示されます。
![2022-03-02 Figure 10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/4f925730-d279-e8c8-0e50-a459e8d1df8a.png)
早速、製品コードや製品名をクエリで出力してみましょう。
![2022-03-02 Figure 11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/78ec656f-59e7-9c44-8f3b-34f0ed57604d.png)
プレビューにより、クエリ結果をこのように拝見できます。製品コードと製品名が表示されました。
![2022-03-02 Figure 12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/ce356785-1c26-ea00-93f1-79a5fa725e7d.png)
:postbox:[お問い合わせ](https://sharperlight.jp/about-us/contact-us/)
tensorflow での前処理、それ、自分で書く？

それ、もう用意されてるかもしれないですよ
https://www.tensorflow.org/guide/keras/preprocessing_layers#%E4%B8%BB%E3%81%AA%E5%89%8D%E5%87%A6%E7%90%86%E3%83%AC%E3%82%A4%E3%83%A4%E3%83%BC
Spreadsheet用セルのJSON情報から特定の項目を取り出す関数

掲題の通り
エラー処理、再帰処理みたいなことはしておらず


```javascript
// cell='{"name":"John", "age":30, "car":null,"claim":{"name":"ABC NEWS"}}'
// =JSONto(A1,"claim","name")
function JSONto(cell,fn1,fn2=null) {
  let obj;
  try {
    obj = JSON.parse(cell);
  } catch(e) {
    console.error(e);
    return null;
  }
  switch(fn2){
    case null:
        return fn1==(obj)?JSON.stringify(obj,null,2):obj[fn1]
        break;
    default:
        return fn1==(obj)?JSON.stringify(obj,null,2):obj[fn1][fn2]
  }
}
```
命名規則（スネークケースとアッパーキャメルケース）でエラーになった経験

# 命名規則（スネークケースとアッパーキャメルケース）でエラーになった経験

## スネークケース
1.単語の区切りをアンダースコア「＿」表す。
　admin_user_comment_creator
2.命名の対象
　メソッド名、変数名

## アッパーキャメルケース
1.キャメルケースの一つで先頭から単語の区切りを大文字で表す。
　AdminUserCommentCreator
2.命名の対象
　クラス名

### 結論
　命名規則を間違えるとうまくコードを読み込んでもらえないので注意が必要。
　また、仮説・検証して解決しなければ命名規則誤り等のスペルミスを疑う。発見しづらいのでスペルミスの可能性も頭の片隅に入れてく。
Markdownのli(箇条書き)のネストしたインデントを戻す方法

## 背景

slackではliのインデントを戻すのはdeleteキーを押せばインデントを戻せるがnotionやメモの場合だと、インデントがうまく戻りませんでした。


* 箇条書き1
    * 箇条書き2
    * 箇条書き3

↑
この`箇条書き3`を`箇条書き1`と同じ階層にしたいです。。

### 結論

* 箇条書き1
    * 箇条書き2
* 箇条書き3

`Shift + Tab`で`箇条書き3`を`箇条書き1`と同じ階層にできました！！！
オイラーのφ関数とユークリッドの互除法

```python:最大公約数(ユークリッドの互除法)
gcd = lambda m, n: n and gcd(n, m % n) or m
```

```python:オイラーのφ関数
eulerphi = lambda n: sum(int(gcd(m + 1, n) == 1) for m in range(n))
```

```python:テスト
>>> [eulerphi(n+1) for n in range(16)]
[1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8]
```
旅の恥はかき捨て、Qiitaの恥はかなぐり捨て

# 今日はただの雑談です、というか恥さらしです
今まで、Chromium の事を、Chronium だと思ってました。
昨日投稿した記事も、そう記載しています・・・
今更修正しません、過去の自分の恥は、修正せずに残します(ただし、記事を見て間違える人がいるかもしれないので、注記は入れます)。

だって、アルミニウムとか「aluminium」じゃん？
Chromium も、末尾が nium だと思うじゃん？

・・・はい、どうみても私が無知なだけです、本当にありがとうございました。
failed to write request: Broken pipe (os error 32)

## 環境
- Windows(WSL)
- rust 1.58
- vscode
## 状況
cargo checkなどは通るのに、vscode上で`failed to write request`というエラーがエディタ上に表示されて、赤線がいっぱいで非常に見づらい

## どうしたか
rust 1.59にバージョンアップしたら解決した。

```shell
$ rustup default 1.59.0 
```

詳細はあまり調べられていない。
エラーを理解するのに気付いたこと

# 最初に
僕はエラーが凄く嫌いです。僕はまだまだ初心者レベルですが、自分の中で一生懸命作ったものに、エラーが出たときの絶望感は計り知れません。ですが、エラーはコードを書いていく上では絶対に避けては通れない道です。腹を括ってエラーと向き合ったら、少し前向きに取り組むようにできてきましたので、まだ初心者である自分がどこに気をつけたかをまとめました。


# エラーと向き合うことの重要性について
エラーの見方として大事なことは、エラーの種類、エラーの詳細、エラーの発生場所です。これが一番大事であると取り組む内に思いました。僕は最初はエラーの種類だけしか見ていませんでした。

なぜなら、エラーの画面は英語ばかりで理解するのが嫌だったからです。ですが、エラーの種類だけを見て検索して色々見ますが、何が自分のものに適応できるかと言いうのがわからなくなって、どんどん調べていって試すけれど、解決しないでやる気が減少していきます。

やっと自分のものと合うものを見つけてもすぐにエラーが起きてやる気が無くなっていって、パソコンの前に座ることが減っていきました。またパソコンの前に座ろうとするけれどまたエラーでわからないことがあることを思うと気が重くなります。やめていく大半の人はこのように辞めていく方が多いのではないかと思います。僕も何度か諦めたことがあります。

エラーについてちゃんと理解するように努めたら、わからないことがわからないという無駄な時間が減り、調べている時にみるべき場所がしっかりしていきました。


# エラー解決のためにまずやるべきこと
エラーが出たときに大事なことはエラー画面をしっかりみることです。経験を積んでいる方は当たり前のことだと思いますが、初心者はまずなんで起きたのか知る必要があると思います。

見るべき場所は**エラーの種類**、**エラーの詳細**、**エラーが起きた場所**です。

例えば車両事故が起きたときに、事故の種類は人身事故なのか物損事故なのか、事故の詳細は脇見運転なのか居眠り運転なのか持病が悪化したのか、事故の発生場所は東京であればどこなのかどこの交差点なのかどこの道路なのかなどがなど事故の詳細を知る必要があります。そうしないと、また同じようなことが起きたときに同じミスをするからです。

- エラーの種類
エラーの種類は、一番上にある太文字で書いてあることです。`TypeError`とか`NameError`とかです。エラーの型を教えてくれます。ここはよく見て、ここからキーワード検索して調べていく方が多いと思います。

- エラーの詳細
エラーの詳細は、エラーの種類のすぐ下にある文章です。TypeErrorのすぐ下に文章が書かれていますが、ここにどんなエラーが起きたのか教えてくれます。Google翻訳をかけると大体理解できます。この時に気をつけるべきことは翻訳をかけるとそのままの意味で翻訳することがあります。例えば`index() missing 1 required positional argument`というエラーの詳細が実際にありました。これをそのままGoogle翻訳にかけると`index（）に必要な位置引数が1つありません`となります。ですが`positional argument`は調べるとキーワード引数と出てきます。index（）に必要なキーワード引数が1つありません`と理解がしやすくなったと思います。このようにプログラミング用語もあるかもしれないのでワードに関しても調べていくとスムーズに理解が進むとおもいます。

- エラーの発生場所
そして最後にエラー発生場所については、ルーティングを理解しどこでエラーが出ているのか把握することが大事です。
ここの時に重要なことがルーティング（HTTPリクエストがあったときにどのようにしてHTTPレスポンスを返しているのか）を、そのフレームワークごとに知る必要があります。僕はDjangoしか勉強していないので他のフレームワークがどう違うのか知りません。
そして何となくチュートリアルだけをしているとここが抜け落ちやすいと思います。僕も実際そうでした。クラスとかインスタンスとか勉強するのにフレームワークの勉強をちゃんとしていませんでした。
チュートリアルをする前にルーティングについて調べて、図を紙に書くか、タブに置いてすぐに見れるようにすると良いと思います。

僕はすぐに忘れてしまうので、紙にこの三つの事項を書いてから調べるようにしています。紙に書くだけで頭の中が整理しますし、わからないことが多く枝葉のように色々と調べていっても紙に書いてあると目的を見失うことがなくなるからです。

# キーワード検索する

これらの背景を基にネットで調べます。３つの事項をしっかり頭に入れるだけで、キーワード検索をかけるときに違いますし、記事を読んでいるときの見方も変わります。

# 質問する
これらを調べて知識をつけて、エラーが解決するときもありますが、解決しないときもあります。そうした場合は質問サイトで質問してみるといいと思います。質問文を書いているときに客観的になるので、意外とこういう時に解決することもあります。

# どうしてもわからない時は明日にする
わからない時は分かりません。自分の固定観念に囚われていることもあるからです。そしたら、その日はやめて違うことをする。例えば、初心者であれば就職したいと思う方もいると思うので、ブログに自分の記事を書いて、少しでも就職に有利なように動くとか、気分をリフレッシュさせるために散歩などしてみたり、もう寝てみたりしてみるといいかと思います。明日もう一度見ると意外とすんなりエラーが解決することもあります。

# それでもわからないものは出てくる
自分でできる限りやっていてもわからないときはお金はかかりますが、質問に答えてくれるオンライン家庭教師などで単発で依頼することも一つの解決策だと思います。

# 最後に
以上で自分が現在エラーに対して取り組むようにしていることです。上記のことを意識することでエラーに対して少し強くなれたと思います。そしてコードを書くようになってから強く思うようになったのは、思い込みがエラー解決の道を大きく阻むということです。プログラミングを始めて自分は思い込みが強いということを自覚できたことは、プログラミングだけでなく私生活でも役立てていきたい思いました。
var,let,constの違い

<h1>主旨</h1>

この記事は過去投稿記事に頂いたコメントを参考として、コードのブラッシュアップを行い、よく分からず使っていたvar,let,constについて自分なり整理する。自分なりに噛み砕いたノート、のようなもの


https://qiita.com/KK1989/items/c5060a09f9986c86d983


<h2>コメント内容</h2>
コメント

「JavaScriptを今から学習するのであれば、変数宣言にはvarではなくconstやletを使う癖をつけたほうが良いかと思います。」
→変数宣言にはconstやletを使おう
→そもそも「var」「let」「const」って良く分かってないなぁ。

<h2>整理</h2>

以下、記事が綺麗にまとめられていた。

https://tcd-theme.com/2021/04/javascript-let-const.html?gclid=CjwKCAiApfeQBhAUEiwA7K_UHzC4AlrlLbrq9_N30dqPPloltGqnBJWkG9sfHWXjzlZgh_p4YB-fxxoCZ8cQAvD_BwE

https://qiita.com/cheez921/items/7b57835cb76e70dd0fc4



<h2>今回のコードでは、、、</h2>

digit以外は「取得のみで再代入しない」
→constで定数宣言

digitはif文条件によって返り値が変わる。(if条件なら返り値"0"+ num,else条件ならnum)
→letで変数宣言
　ちなみにこれをconstにしたらエラー吐きました
　「Uncaught SyntaxError: Missing initializer in const declaration」

と言う感じで描き直す。

```js:clockEasy.js
 //時間が更新されるように時計機能を函数「clock」とまとめる

  function clock() {

   //②の前準備　曜日を表す各文字列の配列定数weeksを宣言
  const weeks = new Array('sun','mon','tue','wed','thu','fry','sat')

// 数字が 1ケタのとき、「0」を加えて 2ケタにする
      const twoDigital = function(num) { //定数twoDigitalを設定する 引数（材料）はnum
        let digit  //変数digitを定義　numに0を加えるためのもの→（返り値をうけるから変数宣言）
         if (num < 10) {digit = "0"+ num; }  //if文 "0"+は文字列として0を足すため
         else {digit = num; }         
         return digit ;  //返り値（結果）としてdigitを返す
    }
 
  // ② 現在日時を表すインスタンスを取得→メソッドを使って時間情報をそれぞれ取得する

  const now =new Date();  //コンストラクタDate()により得た日時情報をインスタンス「new」に格納　newの中に現在の時間情報が全部入っている

  const year = now.getFullYear();
  const month = twoDigital(now.getMonth() +1 );        // 困る　月が２月なのに1月 → なので結果に1足す(10行目)
  const day = twoDigital(now.getDate());
  const week = weeks[now.getDay()];          // 困る  weeksがなければ曜日が数字表記 → なので、配列Arrayを使用して数字を曜日に変換するインスタンス「week」を作成し、代入　（4,13行目）
  const hour = twoDigital(now.getHours());
  const minute = twoDigital(now.getMinutes());
  const second = twoDigital(now.getSeconds());

 //　HTML: <div id="clock_date">(ココの日付文字列を書き換え)</div>
  document.getElementById('clock-date').textContent
   = year + '/' + month + '/' + day + '/' +week;

 //　HTML: <div id="clock_time">(ココの時刻文字列を書き換え)</div>
  document.getElementById('clock-time').textContent
   = hour + ':' + minute + ':' + second;
  }

 // 上記のclock関数を1000ミリ秒ごと(毎秒)に実行 

 setInterval(clock, 1000);

```

<h2>感想</h2>

変数、定数宣言の使い方をつかめた。
const、letを使う癖をつけた方が良いと言うのは、「今回の簡単な時計機能であれば、無視できるけど、規模が大きくなれば誤作動の原因可能性が高いから、この使い方を早めから慣れといた方が良い」て事なんでしょうね。指摘箇所を整理し直すのは、ぼんやり使ってたものが整理されて良いですね。

（他にも同記事にコメント貰ってるんで、このシリーズ続きます、、、）
Azure DevOps Server #2-3 Azure DevOps Server環境でVB6のビルドを改善する

**Chapters**

📘 **Chapter #1**
　📗 **Chapter #1-1**　[継続的インテグレーション（CI）構築](https://qiita.com/tfukumori/items/ef8314857ecb545c4b15)
　📗 **Chapter #1-2**　[継続的インテグレーション（CI）手順](https://qiita.com/tfukumori/items/11d24a5eee8d77a17a80)
📘 **Chapter #2**
　📗 **Chapter #2-1**　[VB6で使用する 環境設定](https://qiita.com/tfukumori/items/37f035694751dc098fcd)
　📗 **Chapter #2-2**　[VB6で使用する プロジェクトの追加](https://qiita.com/tfukumori/items/68aca8cdc04fe76d6eee)
　📗 **Chapter #2-3**　[Azure DevOps Serverの環境でVB6のビルドを改善する](https://qiita.com/tfukumori/items/89dc4cd1651991f075bb)
📘 **Chapter #A**
　📗 **Chapter #A-1**　[バージョンアップ TFS 2018 Update 1 → Update 3、検索サービスの分割](https://qiita.com/tfukumori/items/778bb2e3d913106beba9)
　📗 **Chapter #A-2**　[バージョンアップ 2019→2019 Update1](https://qiita.com/tfukumori/items/7f149928a6e413afe755)
　📗 **Chapter #A-3**　[バージョンアップ 2019 Update1→2020.0.1 + Patch 1](https://qiita.com/tfukumori/items/8d7a9617924f42cbe04f)

---

# 概要

- [VB6で使用する 環境設定](https://qiita.com/tfukumori/items/37f035694751dc098fcd)、および[VB6で使用する プロジェクトの追加](https://qiita.com/tfukumori/items/68aca8cdc04fe76d6eee)を実施した環境で、VB6の一括チェックアウト、一括ビルドを行うスクリプト（バッチファイル）について記載します。

# 前提

- ビルド成果物（*.exe）はリポジトリで管理し、一括チェックアウト、一括ビルド（コンパイル定数指定）はスクリプトで実施しますが、チェックインは手作業で行うことを想定しています。
- 構成管理システムとしては、TFVCを想定しています。
- Azure DevOps Server 2010に接続したTeam Foundation Explorer 2010の`tf.exe`を利用します。

# 手順

## (1) 一括チェックアウト

```bat
REM 変数設定
SET TFEXEPATH="C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe"


REM APP1
SET PROJECTDIRNAME=APP1
SET PROJECTNAME=APP1.vbp
cd %PROJECTDIRNAME%
%TFEXEPATH% checkout %PROJECTNAME%
cd ..\


REM APP2
SET PROJECTDIRNAME=APP2
SET PROJECTNAME=APP2.vbp
cd %PROJECTDIRNAME%
%TFEXEPATH% checkout %PROJECTNAME%
cd ..\


pause
```

## (2) バージョン変更

- 必要に応じ、IDEでバージョン変更。
- リビジョンの自動インクリメントのみでよい場合はビルドでインクリメントまで行われるため、IDEでの作業は不要。

## (3) 一括ビルド

- APP1は、コンパイル定数により別ファイル名とすることを想定

::: note info
`VB6.EXE`の`/make`コマンドは、プロジェクトファイルに保存されたPath、EXEName、および Title プロパティの現在の設定を利用してコンパイルします。
:::
::: note info
自動インクリメントを有効にしている場合は、自動インクリメントおよびプロジェクトファイルの保存も自動的に行われます。
:::

```bat
REM 変数設定
SET TFEXEPATH="C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe"
SET VB6EXEPATH="C:\Program Files\Microsoft Visual Studio\VB98\VB6.EXE"


REM APP1_1
SET PROJECTDIRNAME=APP1
SET PROJECTNAME=APP1.vbp
SET TARGETEXENAME=APP1_1.exe
cd %PROJECTDIRNAME%
%TFEXEPATH%  checkout %TARGETEXENAME%
%VB6EXEPATH% /make %PROJECTNAME% /d COMPILECONSTHOGE=1
copy APP1.exe %TARGETEXENAME%
cd ..\


REM APP1_2
SET PROJECTDIRNAME=APP1
SET PROJECTNAME=APP1.vbp
SET TARGETEXENAME=APP1_2.exe
cd %PROJECTDIRNAME%
%TFEXEPATH%  checkout %TARGETEXENAME%
%VB6EXEPATH% /make %PROJECTNAME% /d COMPILECONSTHOGE=2
copy APP1.exe %TARGETEXENAME%
cd ..\


REM APP2
SET PROJECTDIRNAME=APP2
SET PROJECTNAME=APP2.vbp
SET TARGETEXENAME=APP2.exe
cd %PROJECTDIRNAME%
%TFEXEPATH%  checkout %TARGETEXENAME%
%VB6EXEPATH% /make %PROJECTNAME%
cd ..\


pause
```


## (4) チェックイン

- Team Foundation Explorer 2010 から手作業で実施する。
英訳する時の補助


[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)


+ [特殊記号の読み方](http://www1.odn.ne.jp/haru/data-list/mark.html)
+ [英語の数詞一覧](https://ja.wiktionary.org/wiki/%E4%BB%98%E9%8C%B2:%E8%8B%B1%E8%AA%9E%E3%81%AE%E6%95%B0%E8%A9%9E%E4%B8%80%E8%A6%A7)
+ [英語の序数1から1000までの表記と読み方一覧](https://kw-note.com/translation/english-ordinal-numbers/)
+ [英語の1月から12月までの表記と読み方](https://eigo.plus/eigohatuon/january)


```
"January",31,
"February",28,
"March",31,
"April",30,
"May",31,
"June",30,
"July",31,
"August",31,
"September",30,
"October",31,
"November",30,
"December",31,
30)
```

```
CASE(MID(Custom__c, 4, 3),
"Jan", 1, "Feb", 2, "Mar", 3, "Apr", 4, "May", 5, "Jun", 6,
"Jul", 7, "Aug", 8, "Sep", 9, "Oct", 10, "Nov", 11, "Dec", 12, 0)
```

```
日曜日　Sunday = Sun. = Su.
月曜日　Monday= Mon.= Mo.
火曜日　Tuesday= Tue.(Tues.) = Tu.
水曜日　Wednesday= Wed.= We.
木曜日　Thursday= Thu.= Th.
金曜日　Friday= Fri.= Fr.
土曜日　Saturday= Sat.= Sa.
```

+ [Row Level Formula to Group by Date](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ifena)

```
CASE(
IF(DAY(Amendment_Date__c) = 1,MONTH(ADDMONTHS(Amendment_Date__c,-1)),MONTH(Amendment_Date__c)),
1,"January",
2,"February",
3,"March",
4,"April",
5,"May",
6,"June",
7,"July",
8,"August",
9,"September",
10,"October",
11,"November",
"December")
```

# 英語での回答例

+ [子の情報を親に参照させる質問](https://qiita.com/Keiji_otsubo/items/414043468f47b78d8d0b)
+ [関連リストのフィールドに表示されているフィールドを増やす【英語の回答例】](https://qiita.com/Keiji_otsubo/items/e3a705f91123b65e8e69)
2022/3/2主にITとかセキュリティの記事(2/2)

次世代無線LAN「IEEE 802.11be」の衝撃　高速化技術(3/1)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/021700130/021700002/

次世代無線LAN「IEEE 802.11be」の衝撃　標準化動向(3/1)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/021700130/021700001/

防衛省が求める「セキュリティー基準」の正体
非格付け情報を保護するガイドライン　以前より存在する「特約」を強化(3/1)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800012/021700166/

物流センター移転の混乱で遅配や欠品　顧客11万人に影響、自動化が裏目に
オイシックス・ラ・大地(3/1)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600011/022400102/

データで未来を予測　DXの新たな潮流に(3/1)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/022400280/022400001/

トヨタ取引先のサイバー攻撃受け、デジタル大臣が注意喚起「速やかに連絡を」(3/1)
https://xtech.nikkei.com/atcl/nxt/news/18/12331/

再燃するAmazonフィッシング、利用された鳥取・京都・神奈川など地名ドメインの謎(3/1)
https://xtech.nikkei.com/atcl/nxt/column/18/00138/022500988/

新OSへの移行は悩みの種、Windows 10は保守すればあと4年使える(3/1)
https://xtech.nikkei.com/atcl/nxt/column/18/01950/021400001/

千葉市で新型コロナ陽性者の個人情報流出、管理職へのメール報告で2週続けて誤送信(3/1)
https://xtech.nikkei.com/atcl/nxt/column/18/00598/121500154/
Laravel: Eloquentでカラムの存在チェックする際のtips

Laravelプロジェクトのdbで任意のカラムが存在するかチェックをする際どうするか。

# Builder
`$user->posts()->count()`
で確認していることが多かった。
これだと、全ての行を数え上げしてしまうので行数が多いと速度が落ちる。
Builderの場合の存在チェックはexists()を用いることで条件に一致した瞬間検索を打ち切ることから速度が速くなる。

# Collection
ではCollectionも同様に`$posts->count()`ではなくexists似たような関数の`$posts->contains()`を使うべきか。

答えは`$posts->count()`
count()はO(1)だが、contains()はO(n)らしい。

countがO(1)である解説
https://zudoh.com/php/implementation-of-count-function
>さてここでようやく実装が見えましたね。
count関数の行っていることはhashtable構造体のnNumOfElementsを返却しているだけなのです。

Collectionの計算量
https://tech.innovator.jp.net/entry/2018/09/27/190322
Alfredブックマークが多くなりすぎた時に使えるアプリ

こんにちは。[Alfred](https://www.alfredapp.com/)というツールを知っていますか？

この記事では、ブックマークを検索できる便利すぎるツールAlfredを使い始めた私が調べたショートカットとtipsについてまとめます。

Alfredはランチャという「アプリを検索できるツール」で、macだとspotlightに該当します。
![spotlight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787586/7607f317-8c21-749f-8e45-fd7587fbe904.png)

詳しい説明は省きますが、業務効率化につながる機能が盛りだくさん。
なんといっても<b>「ブックマークを検索できる」</b>機能に惹かれる！
散乱してもはや管理しきれないブックマークを開く手間を省いてくれます。

Alfredの詳しい説明はこちらをどうぞ。
*無料版でも強力なツールでしす。
[Alfredを使いこなせてない君に！【Alfredの使い方完全版】](https://qiita.com/jackchuka/items/ccd3f66f6dd00481b98b)

## ブックマーク検索、 アプリ検索、 ファイル検索
command + space
*私は検索窓の表示をcommand + spaceにしています。
デフォルトでは使えないので
Features > Web BookmarksのChrome Bookmarksにチェックをつけてください。

## 検索結果のプレビュー表示
検索結果にカーソルを合わせてshift

## 検索サイト指定
検索バーで

1. Google
google [検索ワード]
2. wikipedia
wiki [検索ワード]

## フォルダ検索
検索バーで

1. 「shift」押してから[検索ワード]
1. 「'」押してから[検索ワード]

## ファイル内検索
検索バーで

in + [検索ワード]

## システム制御
検索バーで

1. スリープ
sleep
2. スクリーンセーバー
screen
3. ゴミ箱を空にする
    emp
4. 再起動
    restart
5. シャットダウン
    shut
6. アプリの非表示
    hide
7. lock
    lock



## Tips
電卓機能

1. そのまま四則演算ができます。
1. =sin()
1. =cos()
1. =tan()
1. =log()
1. =sqrt()

以上全て無料でできます！

有料版もすごく良さそう。ぜひ使ってみてください！
[Alfred](https://www.alfredapp.com/)
【React】ルーティングした際にpropsを渡す方法

## はじめに
　本記事は、プログラミング初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## ルーティングした際にpropsを渡す方法
以下のように記述することでルーティングした際にpropsを渡すことができます。
ルーティングはreact-router-dom v6で設定しています。

``` App.jsx
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { User } from './containers/User';


function App() {
  return (
    <Router>
    {/* <Router>で<Routes>を囲む */}
    <Routes>
      {/* path="Url" element={コンポーネント} */}
      {/* urlに:keyを記述 */}
      <Route path="user/:id" element={<User />} />
    </Routes>
  </Router>
  );
}
export default App;
```

```User.jsx
import React from 'react'
import { useParams } from 'react-router-dom'

export const User = () => {
  // useParamsでパラメーターを受け取ることができる
  const { id } = useParams()
  return (
    <>
      <div>ユーザー情報画面</div>
      <p>ユーザーIDは{id}です。</p>
    </>
  )
}
```
UNIXコマンド 引数について

僕は、このコマンドを見て、どういう構造になっているかよくわかりませんでした。
```shell
$ hoge -v -lv foo -- -l bar
```
普段、何気なく使っているCLIコマンドですが `--` などが出てくると、よくわからなくなってしまう時があります・・・。
なので、コマンドを整理してみましょう。

### argument (引数)
引数はコマンド名を含めた、コマンドラインに与えられた文字列全体の配列です。
配列の最初にあるのが、コマンド名ということですね。
コマンドラインに与えられたコマンド名もオプションも、パラメータも全て、引数に含まれます。
```shell
$ ls -la /tmp /var/tmp
arg0 = ls
arg1 = -la
arg2 = /tmp
arg3 = /var/tmp
```
### option (オプション)
オプションは　コマンドの挙動を変えるために与えられるものですね。
`-h` のようなものは short と呼ばれ
`--help` のようなものは long と呼ばれます。 

```shell
$ ls -la --help /tmp /var/tmp
option1 = -l
option2 = -a
option3 = --help
```
### parameter (パラメータ)
パラメータはコマンド、もしくはオプションに情報を与えるものです。
例えば、`-o file`の場合 `file` は `-o`オプションにとってのパラメータです。
また、`cat hoge.txt` の場合は `hoge.txt` は `cat` のパラメータですね。

そして、曲者の`--`ダブルダッシュですが
これはオプションのように解釈されてしまうパラメータを渡すために使われます。
`--`で区切った後の引数はオプションではなく、パラメータとして扱われます。
```shell
$ ls -l -- -a
option1    = -l
parameter1 = -a
```

---
### 参考
https://stackoverflow.com/questions/36495669/difference-between-terms-option-argument-and-parameter/36495940
Composeを使っているプロジェクトのbuildSrcにAGPの依存を追加するとビルドがコケる件

## 問題

Composeを使っているプロジェクトで、LibraryExtensionなどを使うため`buildSrc/build.gradle.kts`にAGPの依存を追加すると、

`org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering`

↑これが出てビルドがコケる。

### 環境

Kotlin: 1.6.10
AGP: 7.1.2
Jetpack Compose: 1.1.0

## 解決方法

`implementation(kotlin("gradle-plugin:${kotlin_version}"))`をdependenciesに追加する。

```buildSrc/build.gradle.kts
plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
    google()
}

dependencies {
    implementation("com.android.tools.build:gradle:7.1.2")
    implementation(kotlin("gradle-plugin:1.6.10")) // 追加
}
```

なぜ直るのかは不明。

参考リンク：https://stackoverflow.com/questions/68759939/couldnt-inline-method-call-remember-into-androidx-compose-runtime-composable
JSLinux:ブラウザでLinuxコマンドをお手軽に叩く

##    はじめに

先日LPICの勉強をしていたところ，Linuxコマンドを叩いて挙動を確認したい場面があったのですが，普段使いしているOSがLinuxではないので，いちいち仮想環境を立ち上げたりやリモート接続するのが面倒だなあと思っていたら，Web上でコマンドを叩くことができるサイトを見つけました．JSLinuxという名前で，JavaScriptで書かれたLinuxエミュレータのようです．

URL:https://bellard.org/jslinux/
##   使い方
上記urlを開くと以下のような画面が表示されるので，自分が使用したいマシンをクリックします．
とりあえずここでは一番上のAlpine Linux 3.12.0のCLIを開いてみます．
少し待つと，，，
![スクリーンショット 2022-03-02 1.25.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510592/a20ff668-a054-cee2-d37d-aafba134a550.png)

以下のように立ち上がりました．
![スクリーンショット 2022-03-02 1.27.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510592/6455a116-9307-2452-076a-6e9de1d6e1d8.png)
デフォルトでは以下のように簡単なpython,c,javascriptファイルが置かれているようです．
gccもできるようですね．
試しに実行してみたら簡単なメッセージが出力されました．
![スクリーンショット 2022-03-02 1.45.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510592/f22ab101-279c-9898-954f-d19a9808d148.png)
画面右下を引っ張ると拡大できました．
これでLinuxコマンドの勉強が捗ります．
画面左下のボタンからファイルアップロードもできるようですね．試してみます．

![スクリーンショット 2022-03-02 1.28.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510592/0d632eb0-21f5-5996-41c8-cd9786a606ea.png)
ACMで無料のパブリックSSL証明書をリクエスト(DNS認証)

これはQiitaに関する私の最初の投稿です。
よろしくお願いいたします。

## はじめに
ACMは、AWSサービスのユーザーに無料のSSL証明書を提供します。良い選択だと思います。
今回はACMで無料のSSL証明書をリクエストしてみます。

まず、Route53でドメインを購入し、そのドメインのパブリックホストゾーンを作成しました。
## 手順
#### 1. ACMコンソール
「証明書をリクエスト」を押します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/8db40544-b459-f500-2fae-ab8f57545440.png)
「次へ」を押します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/030d7402-c323-95f8-19f1-b5a1f7461745.png)

#### 2. SSL証明書の情報入力
DNSで認証する方が簡単だと思います。 さらに、SSL証明書を自動的に更新できます。
次に、[リクエスト]を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/d4555667-22aa-6b87-3c8b-2aa82b6a00c3.png)

#### 3. SSL証明書検証
SSL証明書の詳細画面で、「Route 53 でレコード」を作成を押します。
(※Route53を使用していない場合は、認証用のDNSレコードを手動で作成できます。 認証に使用されるDNSレコード情報は、SSL証明書の詳細画面に表示されます。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/64015ab2-244a-1e42-6b79-5061e104763e.png)
次に、Route53でDNSレコードを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/5ff4558a-2ca3-a9fd-d6c6-9b5e3b68c41a.png)

#### 4. 結果
SSL証明書が発行されました。
このSSL証明書は、ALB、CloudFront（リージョンus-east-1で作成）などのAWSサービスに使用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1901067/b05530ee-0bc0-7c1e-3a10-39740362581d.png)

## Document
[1][Requesting a public certificate]
https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-public.html

[2][DNS validation]
https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html
Rails list値の差分比較

## TL;DR

list - listで差分がでる

## なぜ、Rails list値の差分比較を書くことになったか

2つのケースで利用した

### 1. WebClient -> RailsAPI -> 外部APIの時のvalidationで利用

現状の実装でRailsApiServerから外部のAPIを叩く実装があり、外部APIもまだvalidation条件がふわっとしていたため、ApiServer側でvalidationを担保しようと思っての実装(Model継承してService層ににがしているので、あまり本質的じゃない)。

### 2. RSpecのresponse bodyの情報チェックの時に利用した

あまりないケースだが、credential情報をちゃんと消しているかなどの簡易チェックに結構有用だった。
また、ResponseBodyの型情報あっております！！って時のチェックでも利用した。

## 例

```sample.rb
list_a = [1, 2, 3]
list_b = [1, 2]
a - b # [3]

obj.keys - obj_without_credential_keys = [ "client_key" ]
```
trackchanges.styを使ってTeXの共同編集を楽にしよう

overleafなどのTeX共同編集システムが一般的になってきた昨今(※2022年頃)、皆様どのように一つのTeXソースを複数の人間でレビューしているでしょうか。
コメント部分に各自決めた色で
```TeX
\color{***}
hogehoge
\color{black}
```
などとしてもいいですが、今回はそれを補助するためのスタイルファイルである、trackchange.styを紹介したいと思います~~決してお金は貰っていませんよ~~。
http://trackchanges.sourceforge.net/

# とりあえず使ってみる
trackchanges.styをサイトからダウンロードしてきてTeXソースと同じディレクトリに起き、
プリアンブル部分に
```TeX
\usepackage[inline]{trackchanges}
```
と書きます。
これだけで、以下の5つのコマンドが使える様になります。
なお、以下のコマンドにおいては、全て```[editor]```の部分は省略可能です。
省略すると、以下のコマンドによって生成された変更は、全て紫色で表示されます。
編集者によって違う色を使いたい場合は後述。

## ```\note[editor]{The note}```
文章に、補記を追記します。
```TeX
1 + 1 = 3です\note{数式モード使いましょうね}
```
と書くと、

1 + 1 = 3です[数式モード使いましょうね]

の様に組版されます。

## ```\annote{Text to annotate}{The note}```
第一引数の文章に、題二引数の文章を補記します。
```TeX
\annote{$1 + 1 = 3$}{そんなわけないだろ}
```
と書くと、

1 + 1 = 3[そんなわけないだろ]

の様に組版されます。
ただし、実際には第一引数の文章には編集者に応じた色で下線が引かれます。

## ```\add{Text to add}```
文章を追記します。
```TeX
\add{これが追記される文章}
```
と書くと、編集者に応じた色で下線が装飾された文章がそこに追記されます。

## ```\remove{Text to remove}```
第一引数の文章に、打ち消し線を追記します。
```TeX
\remove{決してお金は貰っていませんよ}
```
と書くと、

~~決してお金は貰っていませんよ~~

の様に組版されます。

## ```\change{Text to remove}{Text to add}```
第一引数の文章に、打ち消し線を追記し、その横に題二引数の文章を追記します。
```TeX
\change{決してお金は貰っていませんよ}{嘘ですほしいですお金ください！}
```
と書くと、

~~決してお金は貰っていませんよ~~嘘ですほしいですお金ください！

と組版されます。

# コメントの表示モードを変える
このままだと、単に共同編集者が個々に適当に編集するのと対して変わらない様に思えます。
が、trackchangesには、コメントの表示モードが存在し、それにより単に編集者からのコメントをその場に表示するだけではなく、**コメントを適用し、古い文章は破棄して表示する**モードや、逆に**コメントを無視し、古い文章だけを表示するモード**が存在します。
これは、プリアンブルでtrackchangesをincludeした際のオプションで指定する事ができます。

## ```\usepackage[inline]{trackchanges}```
コメントをその場で表示します。

## ```\usepackage[finalold]{trackchanges}```
コメントをすべて無視して組版します。~~なんのためのコメントだ~~
例えば、この状態で
```TeX
\change{決してお金は貰っていませんよ}{嘘ですほしいですお金ください！}
```
と書くと、

決してお金は貰っていませんよ

だけが表示されます。

## ```\usepackage[finalnew]{trackchanges}```
古い文章をすべて破棄し、コメントを適用して組版します。
例えば、この状態で
```TeX
\change{決してお金は貰っていませんよ}{嘘ですほしいですお金ください！}
```
と書くと、

嘘ですほしいですお金ください！

だけが表示されます。

## ```\usepackage[margins]{trackchanges}```
元の文章をその場に残し、変更やコメントを組版後のページの右側にまとめて表示します。
wordの校閲機能つかった事ある場合はあんな感じと思うとわかりやすいかも。

## ```\usepackage[margins]{trackchanges}```
元の文章をその場に残し、変更やコメントを組版後のページの下側にまとめて表示します。

# 編集者毎に色を変える
実際に使う際は、共同編集者は2人や3人だったりします。
その際には、```\addeditor{editor_name}```コマンドを使います。
例えば、
```TeX
\addeditor{Yamada}
\addeditor{Suzuki}
```
などです。
この後に、上記の5つの編集コマンドに対して、```[editor_name]```オプションを作用させます。
例えば、
```TeX
\add[Yamada]{山田の文章}
\add[Suzuki]{鈴木の文章}
```
などです。
これにより、山田さんのコメントと、鈴木さんのコメントが違う色で表示され、かつコメントを入れた人間の名前が出るようになるため、誰のコメントなのかがわかりやすくなります。

# 他発展的な使い方
他、発展的な使い方は公式サイトのドキュメントから見れます。
http://trackchanges.sourceforge.net/help_stylefile.html#advanced_usage

# 最後に
trackchangesを用いることで、複数人の共同編集者からコメントが入った論文のソースファイルがあった場合、
投稿者は深いこと考えずにfinalnewにして投稿すればいい事になります。
とても楽ですね~~本当にそんなうまくいくかなぁ…~~！

ただし、一部の雑誌では推奨になっていますが、すべての雑誌で使えるかどうかはよくわかりません。
例えば、[AGU出版](https://www.agu.org/-/media/Files/Publications/Latex_submission_guidelines_Jan282022.pdf?la=en&hash=ED903B780A647D32ACC033484F318100)などでは推奨になっているんですが、普通にlatexdiffして変更をtrackしろ、という雑誌もまだまだあると思います。
また、悲しいかな日本語は必ずしもうまくいかないこともあります。
これらの事を見極めた上で、使うか使うまいか決めていきましょう。
RSpec include matcherあるのにexclude matcherないのかと思ったら速攻作れた話

## TL;DR

Negated Matchersを利用して、matcherを作成すれば終わる。


## Exlude Matcherを作る(秒で終わる)

```sample_spec.rb
RSpec::Matchers.define_negated_matcher :exclude, :include
```

## リファレンスに普通に記載がある

```
Negated Matchers
Sometimes if you want to test for the opposite using a more descriptive name instead of using not_to, you can use Matchers.define_negated_matcher:

RSpec::Matchers.define_negated_matcher :exclude, :include
include(1, 2).description # => "include 1 and 2"
exclude(1, 2).description # => "exclude 1 and 2"
While the most obvious negated form may be to add a not_ prefix, the failure messages you get with that form can be confusing (e.g. "expected [actual] to not [verb], but did not"). We've found it works best to find a more positive name for the negated form, such as avoid_changing rather than not_change.
```

[rubydoc.infoより転載](https://www.rubydoc.info/gems/rspec-expectations/RSpec/Matchers)
RSpecのbefore_actionのテストrequest specで書く

### TL;DR

mock class(Controller)を作成して、routingを追加して作成する

## なぜrequest specでbefore_action を書くことになったのか

抽象化しているまたは、ApplicationControllerで全てに
適応する、メゾッドのテストを記載しないといけなくなり、controller specは使えず(anonymous controllerは利用できないため)対応を考えた。

## 想定しているcontroller

```application_controller.rb
class ApplicationController < ActionController::Base
   before_action :authenticate

   def authenticate
       // headerからauth処理関係
   end
end
```

上記の問題は(実装もあるがテストで)、ApplicationController をrouting実装されておらず、request specでテストが記述しづらい。

ので、[stack overflow](https://github.com/rspec/rspec-rails/issues/1596)
をもとにMockControllerを実装した

```application_controller_spec.rb
describe 'Host header attack defense', type: :request do
  before do
    mock_controller = Class.new(ApplicationController) do
      def index
        render json: { ok: true }
      end
    end
    stub_const('MockController', mock_controller)

    Rails.application.routes.disable_clear_and_finalize = true
    Rails.application.routes.draw do
      get '/mock', to: 'mock#index'
    end
  end

  after { Rails.application.reload_routes! }

  context '#authenticate' do
    let(:headers) { { "Content-Type": "application/json" } }
    subject {  get '/mock', headers: headers }
    it { is_expect.to eq 200 }
    // 他にわしゃわしゃ
  end
end
```

個人的には結構、汎用性高くて好みです。(test onlyのroutingを記述しなくて済む)。
抽象化した場合(Concerns使ってもええんやで)、ApplicationControllerや継承元となるControllerのテストを書く時楽ちんですが、これ重くなるんじゃない？とも思ってる。

他に書き方あったら教えてください。
今日からQiitaを書こうと思います。

今日からQiitaを書こうと思います。

# なぜこう思ったのかというと
1. 学んだ技術を後々に残しておきたいから
2. Qiitaを書いてマークダウンに慣れてかっこいい、読みやすいプルリクエスト、readmeを書くため
3. Qiitaで記事を書いてる人かっけぇなぁと思うため(LGTMランキング○位！の人とか)

の3点です。

大体書いてる人はこれのうちどれかなのかなとか自分は思います。
他の書いてる人の理由気になる。

## 目標

更新ペースは2,3日に１記事書く。
いつかランキングに載ったりとかもしてみたいけどそんな高い目標は持たないで続けることを心がける！

## 最後に
これからreactとかtypescriptとか書いていきたいからわかったことはどんどん残していきたい。頑張るぞ
【2022年版】Raspberry Piを始めたい！

# Raspberry Piを入手したい！ 

　昨今の某ウイルスと物流の停滞により，Raspberry Piの全シリーズが入手することが難しい状況です．特に今年はRaspberry Piの収穫が少ない不作の年で，ネット通販でも店頭でも"Out of Stock"の文字が．

　Raspberry Piシリーズは，Raspberry財団とライセンス契約を結んだRSコンポーネンツとelement14が製造・販売を行っています．RSコンポーネンツは，さらに製造をSONYに委託しています．日本国内においては，愛知県にあるSONYの稲沢工場で製造が行われているそうです．そのため，国内で販売されているRaspberry Piはイギリス製 or 中国製（element14) or 日本製の3種類となります．(以下のデザインスパークの記事参照）
https://www.rs-online.com/designspark/sonymanufacturesraspberrypi

　さらに，日本国内においてはIODATAもRaspberryPiの製造を行っていましたが，公式サイトによるとRaspberry Pi Zero WHは2021年11月17日に生産終了となっており，今後生産される見込みはありません．他のRaspberry Pi 3,4などは一時受注停止となっております．（以下のIODATAのHP参照）
(https://www.iodata.jp/product/pc/raspberrypi/ud-rpzwh/index.htm)

　それなら，海外から取り寄せれば，，，と思うかもしれませんが，海外向けに作られたRaspberry Piは技適のマークがついていないものもあり，そういったものは国内での使用できませんよね，，，．

そこで，今回は国内向けに作られたRaspberry Piを販売しているサイトを紹介します!
（Raspberry Pi 400を除く）

## 1, KSY
なんと，Raspberry Pi Zero WHのセットなら在庫があります（2022年3月2日現在）
他のシリーズの在庫は0でした．

https://raspberry-pi.ksyic.com/main/index

## 2, RSコンポーネンツ
3月2日現在，Raspberry Piのどのシリーズも在庫切れとなっています．
今年1月中旬にRaspberry Pi 4B+（8GB)を予約したのですが，到着予定は3月下旬．今購入しても到着は2022年11月11日とのことでした．

https://jp.rs-online.com/web/c/raspberry-pi-arduino-development-tools/raspberry-pi-shop/raspberry-pi/

## 3, 秋月電子通商
Raspberry Pi 3 B（国内製造）なら1人1つ購入できます．しかし，以前は5500円で購入できていたのですが，現在は6200円と少々値上がりしております．

https://akizukidenshi.com/catalog/goods/search.aspx?search=x&keyword=Raspberry+Pi&image=%8C%9F%8D%F5

## 4, 共立エレショップ
現在はどのシリーズも在庫は0ですが，
時々，急に入荷をするので目が離せません．

https://eleshop.jp/shop/goods/search.aspx

## 5, スイッチサイエンス
1ヶ月前からどのシリーズも在庫0となっております．

https://www.switch-science.com/catalog/list/?keyword=Raspberry+Pi

## 6, 千石
遥か昔から在庫がないような気がします．

https://www.sengoku.co.jp/mod/sgk_cart/search.php?cid=5778

## 7, ヨドバシの通販
現在はどのシリーズも在庫は0ですが，
共立エレショップと同様に，急に入荷をするので目が離せません．

#### 8,　アマゾン
もの凄く値段が高騰しており，本来2000円もしないRaspberry Pi Zero WHが1万円近くで販売されている場合もあります．

# 結論
　Raspberry Piは現在入手しにくい状況であるものの国内製造を行っている3Bや，わずかに残っているRaspberry Pi Zero WHは入手することができそうです．
（2022年3月2日現在）
【AWS】メトリクスフィルターとサブスクリプションフィルターの違い(メモ)

- メトリクスフィルター：簡易的なログの監視で使用
- サブスクリプションフィルター：Lambdaを呼び出すなどの柔軟な監視ができる

参考サイト：https://dev.classmethod.jp/articles/notify-error-cloudwatch-logs-with-lambda/
[Ansible] 既に入ってるのに"ERROR! The ec2 dynamic inventory plugin requires boto3 and botocore."と言われたときの対処方法。

# はじめに

`aws_ec2`インベントリプラグインを使いたくて、boto3とbotocoreをインストール。

https://docs.ansible.com/ansible/latest/collections/amazon/aws/aws_ec2_inventory.html

```
$ pip install boto3 botocore　# boto3とbotocoreをインストール
```

いざansibleコマンドをすると、以下のようなことを言われる。

```
ERROR! The ec2 dynamic inventory plugin requires boto3 and botocore.
```

boto3とbotocoreをインストールしろとのこと。
ええ……。

# 解決方

yumでboto3をインストールします。

```
$ sudo yum install python-boto3
```

botocoreに関してはインストールしなくても大丈夫です。
以下を実行しても、「既に入ってるぜ？」と言われます。どっちだよ。

```
$ sudo yum install python-botocore 
```

# おわりに

githubのissueを見ると同じ話題でそれなりに盛り上がっていました。
遭遇しやすいエラーなのかもしれません。
Laravelエラー：新しいルーティング作ったぞ！=>「404 not found」

ある日laravelのプロジェクトを触っていた時に出会ったエラー
いつも通りweb.phpにroutingを追加、controllerを作成よしアクセスしようと思ったら404 not foundの文字が。
pathはあってる、タイポもしていない、なぜエラーが出るのか理解に時間がかかった。

# 原因
原因はルーティングの各順番を間違えていた。
初歩的なミスであったが、エラーコードから読み取ることができず時間がかかった。
ルーティングは上から読み込まれるので、hogeでアクセスしたつもりが{user}として読み込まれてしまい上手く動かない。

```web.php
Route::get('/users/{user}', 'User@show');
Route::get('/users/hoge', 'User@hoge');
```


正しくは

```web.php
Route::get('/users/hoge', 'User@hoge');
Route::get('/users/{user}', 'User@show');
```

「/」で区切ってあるならok

```web.php
Route::get('/users/{user}', 'User@show');
Route::get('/users/some/hoge', 'User@hoge');
```


# これで解消しなかった場合
cacheを消せば動く可能性がある。

```:terminal
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
```

キャッシュの再読み込みなど参考
https://qiita.com/Ping/items/10ada8d069e13d729701
【Ruby on Rails】HerokuとDBの紐付け方法

前提として
---

・HerokuはPostgreSQLを使用しているため、もし”gemfil”の”group :development do”配下でPostgreSQL以外を設定している場合はDBが使用出来ないので、注意下さい。
※例えば、”gemfil”の”group :development do” 配下に ”sqlite” を設定しまっている場合など。この場合は、”group :development, :test do”配下に移動するなど設定変更が必要。”gemfil”を変更したら、忘れず `bundle install` か `bundle update` を実行して下さい。


## 参考にした記事

## 1.　まず、HerokuとGitリポジトリを紐付ける
https://blog.tanebox.com/archives/630/

## 2.　Heroku PostgresをRailsアプリで利用する手順（Rails）
https://qiita.com/NaokiIshimura/items/550ca82e8e57aaea5582





## 1. まず、ログイン
```
% heroku login
```

## 2. Gitリポジトリとherokuが紐付けされているか確認
下記のコマンドでリポジトリ一覧にDBの設定をしたいherokuが表示されていない場合は次の手順 *3. GitリポジトリとHerokuを紐付ける* で紐付けを行います。
```
% git remote -v
originhttps://github.com/〜〜省略〜〜〜.git (fetch)
originhttps://github.com/〜〜省略〜〜〜.git (push)
```

## 3. GitリポジトリとHerokuを紐付ける。
※＜＞はコマンドではありません。
※アプリ名を忘れてしまった人はHerokuのWebブラウザからも確認できます。
```
% heroku git:remote -a ＜紐付けたいherokuのアプリ名＞
```

## 4. HerokuのDBのURLが紐づいているか確認。
`heroku config`コマンドでDATABASE_URLを確認する。　
※URL設定が出来ていれば、下記のような表示がされると思います。
```
% heroku config
=== ＜アプリ名＞ Config Vars
DATABASE_URL:             postgres://＜URL＞
LANG:                     en_US.UTF-8
RACK_ENV:                 staging
RAILS_ENV:                production
RAILS_LOG_TO_STDOUT:      enabled
RAILS_SERVE_STATIC_FILES: enabled
SECRET_KEY_BASE:          ＜省略＞
```
Railsの「config/database.yml」というファイルで、HerokuのDBのURLを設定することで、アプリとHerokuのDBとが紐付されるようです。

## 5. デプロイしたアプリでマイグレーションを実施
```
% heroku run rake db:migrate
```

この後、HerokuのWeb画面からGUi操作で手動デプロイしてDBにアクセスした画面表示が可能になりました。

ちなみに、"git push"したら自動でデプロイ出来るようにHerokuで設定できるので、設定しておくとコマンド操作が省略出来るので楽です。
Windows10でGitHubを始める～⑥-0.Git～GitHub間の認証について

個人学習メモ。

# 1.GitローカルリポジトリとGitHubリモートリポジトリ連携方法
[【GitHub公式】Gitのセットアップ手順](https://docs.github.com/ja/get-started/quickstart/set-up-git)によると、手元のGitローカルリポジトリとGitHubのリモートリポジトリを連携するための認証方法は以下4種類あるらしい。

 - HTTPS接続
   - ①GitHub CLI
   - ②Personal access token
   - ③Git Credential Manager (GCM) Core
 - SSH接続（④鍵認証）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/aa606712-8d96-2091-7a22-0701b2cff44f.png)

GitHub公式ドキュメントによると、現在推奨されているのは以下二つの模様。
 - GitHub CLI
 - Git Credential Manager

上記2つはGitにGitHubの認証情報をキャッシュするため、自身で鍵の管理をしなくていい。

設定によってはGitHub側でSSH認証しか許可していないケースもあるらしいので、その場合はSSHの鍵を作成して認証を行う必要がある模様。

また、SAML SSOを使用する組織が所有するリソースにアクセスする場合はPersonal Access Token(PAT)を使用する必要がある。

# 追記
[GitHub公式ドキュメント](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github)によると、GitHub CLIでSSH鍵認証もできるようだが、検証まではできていない。

# 参考
[Windows10でGitHubを始める～⓪Gitの概念とインストールソフトの種類](https://qiita.com/emiki/items/5c8e52cf6b8506015462)
[Windows10でGitHubを始める～①Gitインストール](https://qiita.com/emiki/items/c0aa0b4da4b63921b153)
[Windows10でGitHubを始める～①'おまけGitホームディレクトリ変更](https://qiita.com/emiki/items/d3f7c054b70171218f64)
[Windows10でGitHubを始める～②GitHubアカウント作成](https://qiita.com/emiki/items/dadf77e9ae1e2b192323)
[Windows10でGitHubを始める～③GitHubでのメールアドレス設定とGitクライアントでのユーザ名・メールアドレス設定](https://qiita.com/emiki/items/4103150a5d7a7cfbff24)
[Windows10でGitHubを始める～③'おまけユーザ名・メールアドレス設定について詳細](https://qiita.com/emiki/items/24212696b54fd16e8af8)
[Windows10でGitHubを始める～④リモートリポジトリの作成（GitHub）](https://qiita.com/emiki/items/5080d948af4a2d0febf5)
[Windows10でGitHubを始める～⑤Githubにプッシュする](https://qiita.com/emiki/items/a2871ab626396e95d9ec)
[Windows10でGitHubを始める～⑥-0.Git～GitHub間の認証について](https://qiita.com/emiki/items/eeaf77d51aadef98aea9)
[Windows10でGitHubを始める～⑥-1.Git操作時のGitHub認証HTTPS（Git Credential Manager）](https://qiita.com/emiki/items/3f2ebda7280374fb3bb7)
[Windows10でGitHubを始める～⑥-2.Git操作時のGitHub認証HTTPS（Personal access token）](https://qiita.com/emiki/items/498b05ede19eee3ad916)
[Windows10でGitHubを始める～⑥-3.Git操作時のGitHub認証SSH編](https://qiita.com/emiki/items/1f1fc0bf0c2c4347148d)
[Windows10でGitHubを始める～⑦GitHubへのPullRequest](https://qiita.com/emiki/items/8619441dca761869177f)

公式ドキュメントが正義↓

https://docs.github.com/ja/get-started/quickstart/set-up-git

https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

https://cartman0.hatenablog.com/entry/2018/10/01/Git(for_Windows)%E3%81%ABGitHub%E8%AA%8D%E8%A8%BC%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E3%81%99%E3%82%8B(2/2)#credentialhelper%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E8%AA%8公式ドキュメントBC%E6%83%85%E5%A0%B1%E3%81%AE%E4%BF%9D%E5%AD%98

https://qiita.com/skkzsh/items/11dd107a0734fec682b8

https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github
40 代おっさんPythonのif、for文について学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 参考資料

<https://www.udemy.com/course/python-kaizen/learn/lecture/26849736#overview>

## if文

構文

```python
if 条件:
    処理内容
elif 条件:
    処理内容
else:
    処理内容
```

重要
pythonでは半角4つのインデントでブロックを判断している。

お試し

```python
a=10
b=20

if a<b:
    print('aはbより小さいです')
elif a==b:
    print('aとbは等しいです')
else:
    print('aはbより大きいです')
```

aとbの値を変えて試してみてください

## for文

構文

```python
for 変数 in データの塊(リストやrange):
    処理内容
```

お試し

```python
mylist = [1,2,3,'利樹大好き']

for i in mylist:
    print(i)
```

出力結果

```python
1
2
3
利樹大好き
```

こんなこともできる

```python
mylist = [1,2,3,'利樹大好き']

for i in mylist:
    print('こんにちは')
```

出力結果

```python
こんにちは
こんにちは
こんにちは
こんにちは
```

print内の処理が4回繰り返す

range関数
関数となっていますが、実際には range 型のオブジェクトを作成します。引数に指定した開始数から終了数までの連続した数値を要素として持つオブジェクトとなります。

お試し

```python
for i in range(0,5):
    print(i)
```

出力結果

```python
for i in range(0,5):
0
1
2
3
4
```

５の手前まで繰り返してくれる

良く使われる使い方

```python
mylist = [1,2,3,'利樹大好き']

for i in range(4):
    print(mylist[i])
```

出力結果

```python
1
2
3
利樹大好き
```

range(4)の場合は０始まりだと認識する

len()を使ったほうが楽

```python
mylist = [1,2,3,'利樹大好き']

for i in range(len(mylist)):
    print(mylist[i])
```

出力結果

```python
1
2
3
利樹大好き
```

＊ここで使った変数iですが最後に入った変数が残っているので注意

ほかの関数

enumerate()
実際の動きを見たほうがわかりやすいので

```python
mylist = [1,2,3,'利樹大好き']

for i,j in enumerate(mylist):
    print(i,j)
```

出力結果

```python
0 1
1 2
2 3
3 利樹大好き
```

インデックスの番号と入っている要素を別々にだす
画面フローでロールバック要素利用

## エラーが発生時にトランザクションをロールバック
画面フローでは、レコード操作した際にエラーが発生することがあります。障害パスとロールバック要素を接続することで、保留中のデータをデータベースに反映することなく、安全にエラーをハンドリングできます。
※ロールバック要素は画面フローのみ利用可能
※winter22追加機能

## 確認例
画面フローで、【取引先】【取引先責任者】のレコード作成機能でロールバック確認します。
### フロー設定画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835427/19cef5a6-d705-1b68-80ca-48a488a36f7b.png)
### 確認シナリオ①(正常登録)
取引先名、取引先責任者姓、取引先責任者名をすべて入力し、「次へ」ボタン押下します。【取引先】【取引先責任者】にレコードが登録されることを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835427/50d18ba5-0034-86ab-91ee-8e318aabfeae.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835427/0fcb87e4-6c0a-5d89-b110-54ae87a4e2e9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835427/d2442dba-6cb1-0f37-fee1-2daa0dd4b445.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835427/7a27addb-1c84-8792-675f-fe478e542265.png)
### 確認シナリオ②(登録異常、ロールバック)
取引先名を入力し、取引先責任者姓、取引先責任者名を空白にして、「次へ」ボタン押下します。【取引先】【取引先責任者】にレコードが登録されず正常にロールバックされること確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835427/7450df8a-2ab0-2aeb-e1db-74f3dd2ba4bf.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835427/0509ffa1-1bbe-849b-ca6f-9b15919cfa43.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835427/d2442dba-6cb1-0f37-fee1-2daa0dd4b445.png)
【まるで関数型】JavaのFunctionクラス入門

# Functionクラスとは？
Functionクラスはメソッドをインスタンスとして扱えるもので、引数などにも代入する事が可能です。

### この記事について
1. 細かいJavaの文法等は扱いません。
2. 対象者：Java初学者
3. ちょいむずかもしれない。
## 使用例
使用例の一つとしてFunctionクラスを引数で取るメソッドを考えてみましょう。

例えば以下のようなメソッドがあったとして、
```java:Main.java
private static class Explanation {
        /**
         * 文字列を成形するメソッド
         */
        public static String formatter(String arg) {
            return arg + "!";
        }
}
```
こんなメソッドを引数に取るメソッドを書きた〜い！と思った時、
皆様はどのようにしてコードを書きますでしょうか。
（こんなメソッドを引数に取るメソッド例↓）
```java:Main.java
private static class Explanation {
        /**
         * 文字列を成形するメソッドを引数に取るメソッド
         */
        public static String function1(??? formatter, String arg) {
            return formatter(arg);
        }
}
```
一般的な解決策としては「**継承**」などが挙がるかと思いますが、正直少し重い。。。
（処理の分割はここでは考えないものとする。）

そんな時便利なのがこのFunction<T,R>クラスです！！
早速Functionクラスを使用して上記の悩みを解消してみましょう。

まずはFunctionクラスとして関数を生成します。
Function＜T,R＞のTが引数の型で、Rには戻値の型を記述します。
また、処理を実行する際は.applyメソッドを使用します。
下記の例で行くとformatter.apply(String);
```java:Main.java
public class Main {
    public static void main(String[] args) {
        // 文字列末尾に「！」を追加する関数（前述のformatterメソッドと同等）
        Function<String, String> formatter = arg -> arg + "!";
    }
}
```
そしたら生成したFunctionの型を引数に取る関数を作成してみましょう。
```java:Main.java
/**
 * Name:
 *      function1
 *
 * Function:
 *      フラグが真だった場合文字列を指定のフォーマットで返却する。
 *
 * @param formatter 文字列を成形する関数
 * @param string    成形される文字列
 * @param flag      処理実行フラグ
 * @return          フラグに応じた処理結果
 */
 public static Optional<String> function1(Function<String, String> formatter, 
                                          String string, 
                                          boolean flag) {
     if (flag) {
         String txt = formatter.apply(string);
         return Optional.of(txt);
     }
     return Optional.empty();
 }
```
お望みのメソッドが作れましたので実行してみましょう。
```java.Main.java
public class Main {
    public static void main(String[] args) {

        // 文字列末尾に「！」を追加する。
        Function<String, String> formatter = arg -> arg + "!";
        Optional<String> rs = function1(formatter, "Pricam", true);

        // 実行結果が存在する場合出力する。
        rs.ifPresent(System.out::println); //Pricam!
    }
}
```

無事出力する事が出来ましたね。

## まとめ

今回はFunctionクラスを使用しました！
正直大人数の開発でこのような小難しい事はしない方が良いですが、
後学の為に是非個人開発等で使用してみてください♪
PHP returnで戻り値を返す

returnによって返される戻り値について下記の点を常に意識できるように備忘録として。
**returnが出来ること：** 処理結果を関数に戻すことができる。
これによりreturnによって返された関数の処理結果を使いまわすことができる。（変数に代入して他の関数の引数として使う等。）

**returnがされた時に起こること：** 関数の処理はreturnがされた時点で終了する。
例えば下記のような関数function convert()ではreturn①の時点でこの関数の処理は終了となるため、return②は発生しない。（ダブらない。）
```php
<?php
function convert(string $datetime)  
    $unix = strtotime($datetime);
    $now = time();
    $diff_sec = $now - $unix;

    if ($diff_sec < 60){
        $time = $diff_sec;
        $unit = '秒前';
    }else{
        if (date('Y') !== date('Y', $unix)){  
            $time =date('Y年n月j日',$unix);
        }else{
            $time = date('n月j日',$unix);
        }
        return $time; //return①
    }

    return(int)$time.$unit; //return②
} 
?>
```
Rails c でテーブル情報を取得するには



テーブル情報取得
ActiveRecord::Base.connection.tables
結果
=> ["schema_migrations", "ar_internal_metadata", "contacts"]

列の名前取得
【テーブル名】.column_names
=> ["id", "name", "email", "content"]

列の情報取得
【テーブル名】.columns
結果
=> 
[#<ActiveRecord::ConnectionAdapters::PostgreSQL::Column:0x0000000117e5ebc0
  @collation=nil,
  @comment=nil,
  @default=nil,
  @default_function="nextval('contacts_id_seq'::regclass)",
  @name="id",
  @null=false,
  @serial=true,
【Swift】スワイプバックで２つ前の画面に戻る

iOSの標準機能である「スワイプバック」で、２つ前の画面に戻りたいと思ったことはないだろうか。
私はある。
<h1>実装例</h1>

```swift
// 現在のNavigationControllerを取得
guard let navigationController = self.navigationController else { return }
var navigationArray = navigationController.viewControllers
// 画面の削除
navigationArray.remove(at: navigationArray.count - 2)
// 配列の再配置
self.navigationController?.viewControllers = navigationArray
```

<h1>解説</h1>
実行している処理としては、 

**画面遷移時に画面を削除することで、遷移後の画面でスワイプバックした時に２つ前に戻れる**
というもの

>画面A→画面B→画面C

と遷移する時に、上記の処理を画面B→画面Cの遷移時の処理に乗せる。
そうすると、画面Cに遷移した時にNavigationControllerは画面Bを忘れ、

>画面A→画面C

となります。

この状態の画面Cでスワイプバックした際に画面Aに戻るので、ユーザー的には２つ前の画面に戻ることになります。
注意としては、画面を消してしまっているので、他のルートで遷移した場合にクラッシュする可能性があるので、取り扱いには充分ご注意を。
CAD/CAM開発

個人でCAD/CAMソフトの開発を行っています。
開発環境は以下の通りです。
- VisualStudio2022
- .NET6
- .NET Standard2.1
- C#

ソフトウェアフレームワークはMVVMパターンを採用しています。
▼画面イメージ
![Viewer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2545621/3e6bef8a-b500-b69c-0a2b-a2443aebc939.png)

今後技術的な記事を投稿していきます。
よろしくお願いいたします。

▼githubリポジトリ
https://github.com/redring1979/redring
Golangによるパスワードの保存

パスワードの保存方法として、

平文のパスワードを単方向ハッシュにかけて保存するのが一般的です。

ハッシュアルゴリズムには`SHA-256`、`SHA-1`、`MD5`等があります。

Golang は `crypto` パッケージで簡単に実装することが可能です。

以下、　`sha256` によるの実装例です。

```go
//import "crypto/sha256"
h := sha256.New()
io.WriteString(h, "my password")
fmt.Printf("% x", h.Sum(nil))
```

# より良い方法

大抵の場合は、暗号化時に使用されたハッシュアルゴリズムが上記のような公開されているものであることが原因で、かつ技術の進歩によりパソコンの計算力も上がり、ハッカーが`rainbow table`を使用することで上記の方法でハッシュされたパスワードをクラックすることが（時間的に）難しく無くなってきたのが現状です。

> `rainbow table` ：ハッシュ結果（ダイジェスト）のデータベース

直接的な解決方法の一つは、自分でハッシュアルゴリズムをデザインすることです。

しかしながら、優良なハッシュアルゴリズムはとてもデザインが難しいのです。

そのため、実際のアプリケーションでは既存のハッシュアルゴリズムを利用して**複数回ハッシュ**することが行われます。

しかし単純な複数回ハッシュでは、ハッカーも当然思いつきます。

そこで、管理者自身だけが知っている**ランダムな文字列をさらに追加して再度ハッシュ**します。

そのランダム文字列を `salt` **(ソルト → 塩)**と言います。料理に**塩\***を\*ひとふりするだけでグンとおいしさが増すように、ハッシュからパスワードをクラックする難易度もグンと上がります。

```go
//import "crypto/md5"
h := md5.New()
io.WriteString(h, "your password")

pw_md5 :=fmt.Sprintf("%x", h.Sum(nil))

//saltを指定します
salt := "your salt"

//salt1+ユーザ名+salt2+MD5を連結します。
io.WriteString(h, salt)
//io.WriteString(h, "username") // ユーザ名を連結しても良い
//io.WriteString(h, salt2) // saltは複数かけても良い
io.WriteString(h, pw_md5)

result :=fmt.Sprintf("%x", h.Sum(nil))
```

これで、`salt`が漏洩していなければ、ハッカーはもし暗号化された文字列を手に入れてもオリジナルのパスワードが何だったのか推測するのはほとんど不可能です。

# もっと安全な方法

しかし、並列計算能力の向上により`rainbow table`を作成するだけの十分なリソースがあればこのような攻撃はすでにまったくもって可能です。

そこで、故意に**パスワードの計算に必要となるリソースと時間を増加**させることによって、誰にも`rainbow table`を作成するのに必要となるリソースを与えないという方法があります。

この方法、アルゴリズムの因子（パラメータ）を調整することで計算強度を上げることにより実現できます。

Golang には既に`scrypt`　というライブラリが用意されていて、以下のその例です。

```go
package main

import (
	"encoding/base64"
	"fmt"
	"log"

	"golang.org/x/crypto/scrypt"
)

func main() {
  password = "your password"

	// saltはご自身のものに入れ替えてください
	salt := "your salt"

	dk, err := scrypt.Key([]byte(password), []byte(salt), 1<<15, 8, 1, 32)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(base64.StdEncoding.EncodeToString(dk))
}
```

`scrypt`の詳細については、こちらに[論文](https://www.tarsnap.com/scrypt/scrypt.pdf)があります。

# 参考記事

[Build web application with Golang](https://astaxie.gitbooks.io/build-web-application-with-golang/content/ja/09.5.html)

[php:安全なパスワードハッシュ](https://www.php.net/manual/ja/faq.passwords.php)

# 元記事

[Golangによるパスワードの保存](https://aifan.jp/2022/02/26/golangによるパスワードの保存/)