OmniAICreator/Qiita-1.07M huggingface dataset:
GitHub ActionsでSecretsから取得した情報をgo:embedで読み込む

# go:embedを使用したファイルの埋め込み

Go言語で外部ファイルを読み込むとき、go:embedディレクティブを使うと実行バイナリにファイルを埋め込むことができます。
変数の前に```//go:embed ファイル名```のように書きます。

## コード
```go:main.go
package main

import (
	_ "embed"
	"fmt"
)

//go:embed secret.pem
var secretKey []byte

func main() {
	fmt.Printf("埋め込んだファイルの中身\n%s\n", secretKey)
}
```

```secret.pem
-----BEGIN PRIVATE KEY-----
FOOBAR0123456789foobar0123456789FOOBAR0123456789foobar0123456789
FOOBAR0123456789foobar0123456789FOOBAR0123456789foobar0123456789
-----END PRIVATE KEY-----
```

## 実行結果
```
$ go run main.go  
埋め込んだファイルの中身
-----BEGIN PRIVATE KEY-----
FOOBAR0123456789foobar0123456789FOOBAR0123456789foobar0123456789
FOOBAR0123456789foobar0123456789FOOBAR0123456789foobar0123456789
-----END PRIVATE KEY-----
```

# GitHub Actionsで動かしてみる

秘密鍵のようにコミットしたくないファイルは Actions secretsに中身を設定して、そこからsecret.pemファイルを作成するようにしてみます。
Actions secretsでは改行がそのままでは使えないようなのでbase64でエンコードしてから設定しています。


```sh
$ base64 secret.pem                    
LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCkZPT0JBUjAxMjM0NTY3ODlmb29iYXIwMTIzNDU2Nzg5Rk9PQkFSMDEyMzQ1Njc4OWZvb2JhcjAxMjM0NTY3ODkKRk9PQkFSMDEyMzQ1Njc4OWZvb2JhcjAxMjM0NTY3ODlGT09CQVIwMTIzNDU2Nzg5Zm9vYmFyMDEyMzQ1Njc4OQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==
```

![secret.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695992/b69ee902-c348-4850-ace6-c1e3fe300c22.jpeg)


```.gitignore
secret.pem
```

```yml:.github/workflows/embed.yml
name: Embed

on:
  push:
    branches:
      - "main"

jobs:
  test:
    name: Embed
    runs-on: ubuntu-latest

    steps:
    - name: Setup Go
      uses: actions/setup-go@v3
      with:
        go-version: '>=1.18'
    
    - name: Checkout
      uses: actions/checkout@v3
    
    - name: Create secret.pem
      env:
        SECRET_KEY: ${{ secrets.SECRET_KEY }}
      run: echo -n $SECRET_KEY  | base64 --decode > secret.pem
    
    - name: Run
      run: go run main.go
```

## Action実行結果
![actions.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/695992/3c1979c2-0f12-9c97-2b8a-c9cf12a1b244.jpeg)


# 参考
[GithubActionsでjsonファイルをSecretsから展開する（Base64）](https://soypocket.com/it/github-actions-json-secrets/)

[go:embed を使った場合に GitHub Actions をどうするか](https://zenn.dev/qsf/articles/513c9dc8ae5dc3)

[『詳解Go言語Webアプリケーション開発』](https://www.amazon.co.jp/dp/4863543727)
数字と文字リテラルを使わずFizzBuzz

### TL;DR
* [第5回 KusoKoudoKaigi | KusoKoudoKaigi](https://kusokoudo.love/kaigi/5/)
* こんなのやってたの知らなかった
* 応募しそこねたので15分で書いた。むしろこのエントリ書くほうが時間かかった。
* 以前書いたやつのリバイバル作品

### 動くやつ
* https://3v4l.org/djZu7

### コード

```php
<?php
class FizzBuzz {
	const THREE = __LINE__;
	const FOUR = __LINE__;
	const FIVE = __LINE__;









	const FIFTEEN = __LINE__;

	public function main() {
		for($i = (int) true;$i <= self::FIFTEEN;$i++) {
			ob_start();
			$this->f($i);
			$this->b($i);
			if (ob_get_contents() == false) {
				echo $i;
			}
			echo PHP_EOL;
		}
	}

	private function f($i) {
		if ($i % self::THREE == false) {
			echo substr(__CLASS__, false, self::FOUR);
		}
	}

	private function b($i) {
		if ($i % self::FIVE == false) {
			echo substr(__CLASS__, self::FOUR, self::FOUR);
		}
	}
}

(new FizzBuzz())->main();
```

### 完走した感想
* `$i = true` のままだと`$i`が`1`になり続けて辛かった
    * https://3v4l.org/VRNBK
    * なるほどわからん
* もっとお題の「強盗に襲われた」シチュを深めてクソコード書きたかった
Electronプロジェクトのライブラリを更新する

Electron製アプリは特段更新がなくても、Electronやnode.jsのバージョンがガンガン上がっていくので定期的にアップデートをしておく必要があるのでさっと済ませる自分用メモ。

# 状況確認
```
npm outdated -g
```
# 更新
```
sudo npm update -g (hoge)
```
- 脆弱制を指摘するメッセージが出たら従う。（npm audit fix --force等）

- 動作確認をする。
ID毎に同じ事象が起きてからの経過日数を求める(SPSS Modeler データ加工逆引き4-11)

# ID毎に同じ事象が起きてからの経過日数（@&#xFFF0;SINCE）

![スクリーンショット 2022-08-02 9.35.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8daf0179-61a1-cecf-d416-81eaf2d9ae53.png)

## 1.想定される利用目的

・顧客の特定行動から特徴量を作成する
・設備ログから特定イベントの経過日数を特徴量にする

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/since.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2022-08-02 9.35.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2f176167-cf7d-eb9c-f8de-f614e5700e02.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2022-08-02 9.38.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/db952a27-1391-1a7b-93bd-e7157dddcaee.png)

b.[フィールド作成]ノードを編集します。ある状態が何行上で起きたかを[@&#xFFF0;SINCE()]で得られます。状態は同じIDで最後に同じ事象が起きたレコードの上方参照なので[@&#xFFF0;THIS(事象)=事象 and @&#xFFF0;THIS(ID)=ID]としています。
![スクリーンショット 2022-08-02 9.39.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/1b011985-861b-11ee-f7a2-1ba3f88c63bf.png)

式ビルダーから@&#xFFF0;関数を探すと簡単に入力できます。
![スクリーンショット 2022-08-02 9.39.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/cecdc1d0-db42-d028-9a68-c53762eca298.png)

[プレビュー]します。
![スクリーンショット 2022-08-02 9.52.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6daf2494-c078-e830-82a8-21e895b28043.png)

c.[フィールド作成]ノードを編集します。同じIDで何行上に同じ事象があるかがわかっていますのでオフセット関数を使って比較するべき日付のデータ（該当日）を作成します。@&#xFFF0;OFFSET(列,1)は列の1行上を参照する関数です。
![スクリーンショット 2022-08-02 9.40.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/60419644-3b6b-8d05-2c86-881e779ba54f.png)

[プレビュー]します。
![スクリーンショット 2022-08-02 9.52.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/272514e3-6a97-0b63-0745-445cca126e97.png)

d.[フィールド作成]ノードを編集します。該当日から[Date]までの日数を求めます。
![スクリーンショット 2022-08-02 9.40.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2a20993d-4bdf-c091-4698-62fc271752bf.png)

[プレビュー]します。
![スクリーンショット 2022-08-02 9.41.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/62c7b561-2d16-967b-e898-d727f86b670b.png)

e.bからdまでをひとつの式にまとめることができます。
![スクリーンショット 2022-08-02 9.42.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/46156248-0216-ab8c-f8e6-06d7be552ffb.png)

#### 注意点

この計算を用いるときはIDと日付で昇順ソートを事前に行っていることを確認してください。

## 4.参考情報

#### IoTデータを扱った記事

https://qiita.com/kawada2017/items/1385a5d4a83154792c12

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
jQuery.each(=$.each)は何でreturn falseでループを抜けるんだ？

## はじめに
jQueryの$.eachは、一般的なforeachと異なり以下の特徴があります。

①break・continueは使えない
②return falseをすることでbreak相当を、returnもしくはreturn trueをすることでcontinue相当をすることができる

コード例としては公式のドキュメントを参照のこと。ドキュメントにはcontinue相当の例はないですが、false以外にしてif以降に処理を書くとcontinue相当の動きをすることがわかります。

https://api.jquery.com/each/

この記事では、①・②が何故なのかを確認します。自分はreturn trueとreturn falseのどっちがbreakでどっちがcontinueなんだ？といつも迷ってググっているので、特に②についてどっちがどっちなのかを理解できることを目指します。

## jQueryのソースコードを確認
というわけでjQueryのeachのソースコードを探したら以下にありました。

https://github.com/jquery/jquery/blob/main/src/core.js

以下該当部分の抜き出しです。
```js
	each: function( obj, callback ) {
		var length, i = 0;

		if ( isArrayLike( obj ) ) {
			length = obj.length;
			for ( ; i < length; i++ ) {
				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
					break;
				}
			}
		} else {
			for ( i in obj ) {
				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
					break;
				}
			}
		}

		return obj;
	},
```

①については、各要素に対しての処理を書いている部分はcallbackというfunctionであり、break・continueが使えるforEachの中身の記述ではないということがわかります。
②については、そのcallbackの戻り値がfalseの時のみbreakし、それ以外の時は次のループを実施するという実装になっているからということがわかりました。

## おまけ ほかの言語(C#(.Net))との比較
以前の記事で同じような内容をC#について書いています。

https://qiita.com/matsumoyu/items/a208ca5adfae8fc1601b

break・continueが使えない理由については同じ理由だろうというのは察しがついていて実際同じだったのですが、戻り値のtrue/falseでbreak・continue相当のことができるのは相違点なので見比べると面白いです。
【Google Spread Sheet】セル数の上限とは何を指しているのか？

# はじめに

GASを使って大量のデータを書き込んでいたところ、以下のように「この操作を行うと、ワークブック内のセル数が 10000000 の制限を超えてしまいます」というエラーが発生しました。
データを入れているのは1000万セルも無いのにおかしいと思い、このエラーが出る条件を調べてみることにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/9368af99-2ff7-b687-c6cc-3aef9fb040ff.png)

# 調査1：まっさらなシートに100列×10万行のセルに書き込む

* 以下のコードの`test1()`を実行して、「シートをクリアして、さらに1行1セルの状態にした後、100列×10万行のセルに書き込む」という操作をしました。
* このコードでは何のエラーも起きず、処理を終了することが出来ました。

```javascript
const SHEET_NAME = "シート1"
const SHEET = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1");

// シートをクリアした後、1行1セルにする。
function initSheet() {
  SHEET.clear();

  const maxRow = SHEET.getMaxRows();
  const maxCol = SHEET.getMaxColumns();
  if (maxRow > 1) {
    SHEET.deleteRows(2, maxRow - 1);
  }
  if (maxCol > 1) {
    SHEET.deleteColumns(2, maxCol - 1);
  }
}

// 100列×10万行で1000万セルに書き込む。
function test1() {
  initSheet();

  const range = SHEET.getRange(1, 1, 100000, 100);
  range.setValue("1");
}
```

# 調査2：100列×10万行のセルに書き込んだ後、20列×50万行のセルに書き込む

* 以下のコードの`test2()`を実行して、「シートをクリアして、さらに1行1セルの状態にした後、100列×10万行のセルに書き込む」という操作をした後、さらに「シートをクリアしてから、20列×50万行で1000万セルに書き込む」という操作をしました。
* このコードを実行すると、`この操作を行うと、ワークブック内のセル数が 10000000 の制限を超えてしまいます`というエラーが発生します。

```javascript
const SHEET_NAME = "シート1"
const SHEET = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1");

// シートをクリアした後、1行1セルにする。
function initSheet() {
  SHEET.clear();

  const maxRow = SHEET.getMaxRows();
  const maxCol = SHEET.getMaxColumns();
  if (maxRow > 1) {
    SHEET.deleteRows(2, maxRow - 1);
  }
  if (maxCol > 1) {
    SHEET.deleteColumns(2, maxCol - 1);
  }
}

// 100列×10万行で1000万セルに書き込み、シートをクリアした後に20列×50万行で1000万セルに書き込む。
function test2() {
  initSheet();

  const range1 = SHEET.getRange(1, 1, 100000, 100);
  range1.setValue("1");

  SHEET.clear();

  const range2 = SHEET.getRange(1, 1, 500000, 20);
  range2.setValue("1");
}
```

# 結論：［表示されているセル数＞1000万］の時にエラーとなる

* 当初は「データの入っているセルが1000万個を超えるとエラーになる」と思っていましたが、上記の調査結果からこの仮説は覆されました。
  * 私の勝手な思い込みでした...
* 結論は「シート上に表示されているセル数が1000万個を超えるとエラーになる」というものでした。
* `test1()`の結果は以下の図の左側のように、シート上に確保されているセルは1000万個ちょうどなので、エラーが発生することはありませんでした。
* `test2()`の場合、以下の様にデータの入っているセルとは別に`表示されているセル`が1000万個を大きく超えてしまうため、結果としてエラーになってしまうようです。
  1. 100列×10万行（＝1000万個）のセルに値を書き込む。
  1. シートをクリアした際にセル中の値は消されるものの、確保したセル範囲（100列×10万行）はそのまま表示されている。
  1. 次に20列×50万行（＝1000万個）のセルに値を書き込もうとするが、この時に表示されるセル範囲（※図の赤＋青＋点線部）は5000万個となるためにエラーとなる。
* また、セル数の上限である1000万個は「1シートあたり1000万セル」ではなく、「1ファイルあたり1000万セル」となるようです。
  * シートを分割すれば回避できると思いましたが無理でした...

![GoogleAppScriptのセル数の上限.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/10704ad3-c7d6-8b43-b00f-5488202dc019.png)

# その他

* 例えば「あるシートを変更する前に、シートをコピーして履歴として保持する」というようなプログラムを組んでいると、ファイル全体で使っているセル数が急増するため、今回の問題が生じる可能性が高いかもしれません。
* 以前に[【Google Spread Sheet】RDBのように複数シートを紐づける方法](https://qiita.com/nkojima/items/5112972fc96a41341e2b)という記事を書きましたが、スプレッドシートでは大規模なデータを保持するのには向いていないと感じました。
  * 1000万個の上限の前に、そもそもスプレッドシート側のパフォーマンスが問題になりそうですが...
gym.render() でpygame is not installed ~ のエラーが出たときの対処法

# 困ったこと
Open AI Gym のenv.render() でエラーが発生してrender が使用できなくなった！というときに試す設定を書き残しておきます。

# pygame is not installed ~ というエラーになる
使用したコードは下記の通りです。
```python
import gym

env = gym.make('CartPole-v0')
observation = env.reset()
for i in range(100):
  env.render()
  observation, reward, done, info = env.step(1)
env.env.close()
```

下記のようにpygame is not installed ~ のようなエラーになる場合、

```terminal
  File "/opt/anaconda3/envs/xxxx.py", line 199, in render
    raise DependencyNotInstalled(
gym.error.DependencyNotInstalled: pygame is not installed, run `pip install gym[classic_control]`
```

ターミナルで下記を追加してみましょう。

```terminal
pip3 install pygame
```

# 参考
- https://bobbyhadz.com/blog/python-no-module-named-pygame
【Unity収益化】AdMobSDKのインポート

AdMobSDKのインポート手順メモ
公式サイトを参考に進める
https://developers.google.com/admob/unity/quick-start

## プラグインのダウンロード
1. 公式サイトにアクセスする
https://developers.google.com/admob/unity/quick-start
1. `プラグインをダウンロード`をクリック
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/7630f9d2-86cf-d6e6-5529-fe1100528999.png)
1. `GoogleMobileAds-v6.1.2.unitypackage`をクリックしてパッケージをダウンロード
:::note warn
最新版をインポートするとビルドエラーが発生する可能性がある
2022/08/14時点、**v7.1.2**で**エラー発生**
:::
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/58e77413-29f9-f3c1-f8a5-059d018e163b.png)

## Unityプラグインのインポート
1. `[Assets]>[Impot Package]>[Custom Package]`をクリック
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/a55e5bca-0faa-5762-3ee6-6bf93aa6187d.png)
1. `[Import]`をクリック
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1719666/51f8582b-fd30-2d28-59c6-15807e43717b.png)
US配列の自作キーボード（7skb、7sPro）をJIS配列設定のwin機にそのまま刺して使えるファームウェアを作りました


# この記事は何か
表題のファームウェアを作りました。
そのhexファイルとソースコードを紹介します。


# 経緯
初めての自作キーボードを作りました。
キットはHHKBベースの配列とスペースバー分割が魅力的な「7sPro」です。

しかし、家でも職場でもPCは基本的にJIS配列設定で、他の人が使用する場合があるなどの都合でUS配列設定に変更することができません。

これまではULE4JISという変換ソフトを活用していましたが、触れるPC全てにこれを導入するのもなんだかなという感じがあります。

そのため、ULE4JISと同等の変換を行うカスタムファームウェアを作成しようと思った次第です。

同じように「JIS設定PCにUS配列キーボードをそのまま刺して使用したい！」という方がいらっしゃるかと思い、ファームウェアとソースコードを公開いたします。



# ファームウェア（hexファイル）
こちらからDLしてください。
https://drive.google.com/file/d/1rP4Tg7jqCkSk_IkTsk2gwHyI9M2Qzqgo/view?usp=drive_link　←2024/1/3更新。viaプロトコル9対応。
~~https://drive.google.com/file/d/1Qv9hHbpHlk7k9BDQ5rf_zfuFqrAMnKny/view~~ 　←旧バージョンのRemap(0.18)用です。

他のファームウェアと同様、Pro Micro Web Updater などで書き込めます。



# ソースコード
githubで公開しています。
https://github.com/p2heycocoon/qmk_firmware_7skb_via_jtu
↑2024/1/3更新。viaプロトコル9対応。

qmk_firmware の `keyboards/salicylic_acid3/7skb/keymaps` の直下に
`via_jtu` が来るように配置して、
QMK MSYSで `make salicylic_acid3/7skb:via_jtu` をすることにより
上記hexファイルが作成されます。

`keymap.c` 内の `// 以下追加` から `// 追加ここまで` がベースから追加した内容なので、
他のキーボードにも同じことをすれば活用できるかもしれません。

hexフォルダ内のファイルは上記「こちらからDLしてください。」のファイルと同じです。

# 特徴
## 良い面
- 上記の通り、JISキーボード設定のWIN機でそのまま使用できるようになります。
- VIA対応です。
- `KC_AT` など、シフト押下後を直接指定するキーコードにも対応しています。
- 変換対象キー（＠や’など）を押しっぱなしで、通常キーと同じ様に連続出力できます。
- 変換対象キーを押したままで、放す前に他のキーを押しても問題ありません。

## 悪い面
- MAC機など、WIN機以外でどうなるか未検証です。
- 変換対象キーをシフトキーといっしょに押したままで、変換対象キーを放す前にシフトキーを放すと別のキーコードが出力される場合があります。（なので、文字入力やプログラミングなどには問題ないと思いますが、ゲームには不向きかもしれません。）

この２番目の「変換対象キーをシフトキーといっしょに押したままで・・・」を解決できそうな案がございましたら、何卒コメントにお願い申し上げます。。。

# 謝辞
7skb、7sProの開発者であるサリチル酸様がqmk公式 https://github.com/qmk/qmk_firmware に公開された `keymap.c` をベースにさせていただきました。ありがとうございます。

変換処理はkoktoh様の https://github.com/koktoh/jtu_custom_keycodes を参考にさせていただきました。ありがとうございます。

# 2022/09/04　追記
KC_PEQL（単独のイコール） KC_PCMM（単独のカンマ）に対応していなかった不具合を修正しました。
（リンク先のhexファイルとgithubのソースコードを修正）

# 2024/01/03　追記
2023年9月にバージョンアップしたRemapに対応するようにソースコード、ファームウェアを更新しました。
コンピュータサイエンス 基礎知識（n進数，論理演算，デジタルデータの表現）

# はじめに
コンピュータサイエンスの基礎について，「[きたみりゅうじ．キタミ式イラストIT塾 基本情報技術者 令和04年．](https://www.amazon.co.jp/%E3%82%AD%E3%82%BF%E3%83%9F%E5%BC%8F%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88IT%E5%A1%BE-%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85-%E4%BB%A4%E5%92%8C04%E5%B9%B4-%E3%81%8D%E3%81%9F%E3%81%BF-%E3%82%8A%E3%82%85%E3%81%86%E3%81%98/dp/4297124513/ref=sr_1_1?crid=OQ1P17GFX089&keywords=%E3%82%AD%E3%82%BF%E3%83%9F%E5%BC%8F%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88it%E5%A1%BE+%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85+%E4%BB%A4%E5%92%8C02%E5%B9%B4+%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E6%8A%80%E8%A1%93%E8%80%85%E8%A9%A6%E9%A8%93&qid=1660449303&sprefix=%E3%81%8D%E3%81%9F%E3%81%BF%2Caps%2C274&sr=8-1)」で学習した基礎知識のまとめ．
今回の内容は，「n進数，論理演算，デジタルデータ表現」．

# n進数
各桁で使える数字がn種類の数，コンピュータはデータを2進数で表現．

**基数と各桁の重み**
	・基数：n進数の n
	・各桁の重み：基数を累乗した数値

**基数変換**
	特定の数値を異なる基数nでの表現に変換。変換方法は「重みを使う方法」「割り算、掛け算を使う方法」がある。2,8,16進数の互いの変換は、8進数を3ビット、16進数を4ビットと考えると楽．

**2進数の負数の表現**
	・先頭の1ビットを符号とする。先頭ビット=0が正、先頭ビット=1が負．
	・特定の数値の「2の補数」表現は、そのまま特定の数値の負の値．
	　「2の補数」＝「特定の数値の各桁を反転（各桁の0,1を入替）させ、1を足した数値」

**2進数の小数点を含む数の表現**
	・固定小数点数：ビット列のどの位置に小数点があるかを暗黙的了解で扱う表現．
	・浮動小数点数：指数表記を用いて数値を扱う表現。±0.m×2^e（基数=2）で表現。符号、正規化した指数e、正規化した仮数mをビットに当てはめる．

# 論理演算
**論理回路**
	論理積回路AND、論理和回路OR、否定回路NOT、否定論理積回路NAND、否定論理和回路NOR、排他的論理和回路EOR(XOR)

**ビット操作**
	ビットを反転：反転させたい位置に1を入れ、排他的論理和EORをとる。例、101の1,2桁目だけ反転させたいとき、101 EOR 011=110とできる．
	特定のビットを取り出す：取り出したい位置に1を入れ、論理積ANDをとる。例、101の1,2桁目だけ取り出したいとき、101 AND 011=001とできる．

# デジタルデータの表現
アナログ情報とは，連続して変化する情報．デジタル情報とは，ある範囲を規定の桁数で区切って数値化された情報．

**ビットとバイト**
	ビット：コンピュータが表現する最小単位．
	バイト：1バイト＝8ビット．

**データの表現**
	画像データ：ビットマップ方式は、画像をドットの集まりで表現。各ドットに色を当てる。色数のデータは、1ドットにつき、2色で1ビットの情報量。フルカラーは24ビット(=2^24色)．
	音声データ：サンプリング周波数（1秒に何回データを取得するか）と量子化ビット数（信号レベルを何ビットのデータで表すか）で表現．

**アナログデータのコンピュータ制御**
	センサ：アナログデータを計測し、電気的な情報に変換する装置．
	アクチュエータ：電気信号を物理的な動作に変換する装置．

**機器の制御方式**
	シーケンス方式：予め定められた順序や条件に従って制御の各段階を逐次進めていく制御方式．
	フィードバック方式：定期的に状態を測定し、目標値とのズレを入力側に戻して反映させることで、出力結果を目標値と一致させようとする制御方式．

参考
>[きたみりゅうじ．キタミ式イラストIT塾 基本情報技術者 令和04年．](https://www.amazon.co.jp/%E3%82%AD%E3%82%BF%E3%83%9F%E5%BC%8F%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88IT%E5%A1%BE-%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85-%E4%BB%A4%E5%92%8C04%E5%B9%B4-%E3%81%8D%E3%81%9F%E3%81%BF-%E3%82%8A%E3%82%85%E3%81%86%E3%81%98/dp/4297124513/ref=sr_1_1?crid=OQ1P17GFX089&keywords=%E3%82%AD%E3%82%BF%E3%83%9F%E5%BC%8F%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88it%E5%A1%BE+%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85+%E4%BB%A4%E5%92%8C02%E5%B9%B4+%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E6%8A%80%E8%A1%93%E8%80%85%E8%A9%A6%E9%A8%93&qid=1660449303&sprefix=%E3%81%8D%E3%81%9F%E3%81%BF%2Caps%2C274&sr=8-1)
>[Qiita Markdown 書き方 まとめ](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1)
jpドメインって誰が管理してるの？


## 勉強前イメージ

JPNICはIPアドレスだもんね

## 調査

### jpドメインの管理者について

現在のjpドメインの管理者、
登録や管理業務を行っているのは `株式会社日本レジストリサービス(JPRS)` になります。

元々は日本国内のIPアドレスの管理を行っているJPNICがjpドメインの登録の管理業務などを行っていました。
しかし2002年にJPRSへ移管されました。
1990年代の後半からインターネットが普及して、jpドメインに対しても利便性の向上を求める声が多くなりました。
その為2000年にJPNICが新会社(JPRS)を設立して、2002年にそちらにjpドメインの管理業務が移管されました。

移管されたからといって関わりが全くなくなったと言えばそうではないです。
jpドメインは民間のJPRSへ移管されましたが、ドメイン名は公共資源という面もあり中立性や公共性が求められています。
その為JPNICは日本のインターネットコミュニティの代表として
jpドメイン名を公共性・中立性を維持できるように運営できているか確認するという業務をICANNと契約しています。
なので実際管理を行っていのはJPRSですが、その管理の形態をチェックしているのはJPNIC みたいな感じで運用されています。

## 勉強後イメージ

元々はJPNICがjpドメインを管理してたのね？
2002年って20年くらい前・・・・
最初にjpドメインが委任されたのは1986年だからほんの40年くらい前にjpドメインができたのか

## 参考

- [JPNICからJPRSへのJPドメイン名登録管理業務の移管について](https://www.nic.ad.jp/ja/dom/ikan.html)
- [JPドメイン名の歴史](https://jprs.jp/related-info/history/jpdomain.html)
Javascriptでのreplaceメソッドの第二引数の関数が理解できた件について

## なぜ記事を書こうと思ったか
  開発の際にJavascriptのreplaceメソッドで第一引数に正規表現、第二引数に関数を使用する際の関数の引数に何の情報が入っているか分からず開発が進まない事があった為、今回replaceメソッドの引数に入る情報をまとめたいと思います。

## replaceメソッドはどのような処理？
　replaceメソッドは簡単に言うと、パターンに一致した部分文字列の一部またはすべてを置換文字列で置き換えた新しい文字列を返します。
簡単な例だと以下のような形です。
```
const greeting = "初めまして、私は田中太郎です。このクラスの田中健太君と友達です。よろしくお願いします。";

// 第一引数が文字列の場合
console.log(greeting.replace("田中", "佐藤"));
// コンソール結果("初めまして、私は佐藤太郎です。このクラスの田中健太君と友達です。よろしくお願いします。")

// 第一引数が正規表現の場合
console.log(greeting.replace(/田中/i, "佐藤"));
// コンソール結果("初めまして、私は佐藤太郎です。このクラスの田中健太君と友達です。よろしくお願いします。")
```

上記のreplaceメソッドは簡単に理解できると思います。自分にとってはこの後の内容が理解に苦しみました。

## replaceメソッドの第二引数に関数を指定した場合について
以下にreplaceメソッドの第二引数に関数を指定した場合の例を記載致します。
```
function replacer(match, regexpMatch1, regexpMatch2, offset, string) {
  return "{小池徹平}";
}
const introduction = "初めまして、私は田中太郎です。このクラスの{佐藤健}と友達です。よろしくお願いします。";
const newIntroduction = introduction.replace(/({佐藤([^}}]*)})/g, replacer);
console.log(newIntroduction);
// コンソール結果("初めまして、私は田中太郎です。このクラスの{小池徹平}と友達です。よろしくお願いします。")
```
このreplaceメソッドの第二引数のreplacerの引数に何が入っているのか分かりませんでした。
簡単に以下にreplacer関数の引数にどのような情報が入っているかまとめます。
- 第一引数(match)
replaceメソッドの第一引数の正規表現に該当する文字列を格納しています。今回の場合は"{佐藤健}"が該当します。
- 第二・第三引数(regexpMatch1・regexpMatch2)
replaceメソッドの第一引数の正規表現の()に囲まれた部分(サブパターン)を格納します。regexpMatch1には正規表現の"({佐藤([^}}]*)})"に該当する"{佐藤健}"が格納され、regexpMatch2には正規表現の"([^}}]*)"に該当する"健"が格納されています。
この第二・第三引数については、正規表現のサブパターンを指定しない場合は存在せず、今回よりも多くのサブパターンを指定する場合は第四引数、第五引数・・・と増えていきます。
- 第四引数(offset)
変数introductionの文字列で何文字目の後に正規表現が合致するかを格納します。今回の場合は21が該当します。
- 第五引数(string)
replaceメソッドをしている変数の値を格納します。今回の場合は"初めまして、私は田中太郎です。このクラスの{佐藤健}と友達です。よろしくお願いします。"が該当します。

上記に書いた事で引数にはどのような情報が格納されているか理解できると思います。

## 最後に
　最後まで読んでいただきありがとうございました〜

## 参考資料
[MDN/String.prototype.replace()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace)
早期リターンって，値を返す関数しか考えてない？

タイトル通り「早期リターンって，値を返す関数しか考えてない？」

初心者入門のプログラム FizzBuzz。回答例は以下のようなものですよね(Python)。

```Python
def fizzbuzz(i):
    if i % 3 == 0 and i % 5 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)
```

これを，「早期リターン」で書くと，とてもみっともないプログラムになります。
読みやすいですか？ 保守性が高いですか? メリットは何?

```Python
def fizzbuzz(i):
    if i % 3 == 0 and i % 5 == 0:
        print("FizzBuzz")
        return

    if i % 3 == 0:
        print("Fizz")
        return

    if i % 5 == 0:
        print("Buzz")
        return 
    
    print(i)
```

んっなわけないですよね。

そもそも，「ネストが深いダメダメプログラム」ってのは，例えば

```Python
def fizzbuzz(i):
    if i % 15 == 0:
        if i % 3 == 0 and i % 5 == 0:
            print("FizzBuzz")
        elif i % 3 == 0:
            print("Fizz")
        else:
            print("Buzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)
```

こんなプログラム書いたら，そもそも，怒られます。
【#50 エンジニア転職学習】WSL2でUbuntu20.04のGo開発環境をつくる

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

3回連続になりますが、Linuxの開発環境を整えようと思います。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
* **WSL2を使用してUbuntu20.04の開発環境構築　←Topics!!**


# WSL2を使用してUbuntu20.04の開発環境構築
先日の投稿でVirtualBox上にUbuntu22.04を導入しました。
https://qiita.com/Chika110/items/9bc531bc3ed83784eae3

問題なく動いているように感じたのですが、全く負荷のかかる作業をしていない状態でも、
**ゲスト・ホストどちらともYouTube等の再生ができませんでした。
他にもBluetooth機器の接続がおかしくなるといった不具合も**でました。
学習時に動画を参考にすることも多いため都合が悪いと思い、
**Linux環境の代替案として今回のWSL2を使用**することにしました。
（調べている過程で分かったのですが、後ほど学習予定のDockerを使用する際に必要な環境のようです）

WSL2をインストール後、
Windowsターミナル上でUbuntuを操作できるようになってからは、
基本先日とやることは一緒です。興味のある方は先日の記事をご覧ください。
### VirtualBox時との違い
* UbuntuはCLIのみ（GUIもあるのかも）
* VSCodeはWindowsに入っているものと共用
### 環境
* ホストOS：Windows11
* Linuxディストリビューション　：Ubuntu20.04
* IDE　：VSCode
* 他インストールしたツール等：
    * Go言語
    * MySQL8.0
    * Git最新版
### WSL2のインストール
使用しているPCの環境によってさまざまなエラーが起きるようです。
私の場合は**Powershellの方で`wsl`コマンドを受け付けてもらえず、
コマンドプロンプトを管理者権限で開いて**、Ubuntuインストール等を行いました。

現在のインストールマニュアルよりも、
「**以前のバージョンのWSLの手動インストール手順**」の方が参考になりました。
そちらに書いてある「仮想マシン有効化」や「カーネルパッケージプログラム」の設定等をひととおりやれば、
無事インストールまでこぎつけるかと思います。

見た目には分かりにくいですが、仮想化環境でUbuntuが動作しており、
Pathの指定もWindows環境は関係なく、通常どおり行えばOKのようです。

https://docs.microsoft.com/ja-jp/windows/wsl/install-manual

### ターミナルやVSCodeの設定
リンク先の動画が端的にまとめれていて分かりやすかったです。
先述のとおりVSCodeはUbuntu上で新規取得する必要がなく、
Windows上のVSCode拡張機能で↓をインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2041988/59d800de-b93a-7e67-78bb-ad940e5c74f6.png)
その後、VSCodeで開きたいディレクトリまで移動して`code .`と実行すれば、
WSL上からVSCodeを使用している環境になります。
画面左下がこのようになっていればOKです。
ターミナルもUbuntuのbashに変更されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2041988/29cfd22e-b94b-e137-3847-6d79a3a063f5.png)

https://www.youtube.com/watch?v=SnJNEtn1Es8


# おわりに
最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。
【PostgreSQL】Error querying database.  Cause: org.postgresql.util.PSQLException: 【エラー】

# はじめに
SpringBootでの勉強中に起きた事象のメモです。

# 環境
Windows10
PostgreSQL
SpringBoot

# 事象
SpringBootでDB接続を行い、DBからSQL取得した値を画面表示させようとした際、以下のメッセージが表示され、DB接続ができないという事象が起きました。

```eclipseコンソール
### Error querying database.  Cause: org.postgresql.util.PSQLException: ERROR: テーブル sample へのアクセスが拒否されました
```

# 考えたこと
アクセス拒否ということは、権限の周りで何かおかしな設定がされているはず。設定ファイルがおかしいのだろう。

# 解決策
DBの所有者を確認します。
＜所有者の調べ方＞
SQL Shell (psql)で以下のコマンドを叩く。
```
①postgres=# \l
```
これで、作成したDB一覧の確認と、所有者の確認ができます。
参考に画像おいておきます。
![DB接続.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613261/06c295fe-062b-e386-f7b1-fd7988281623.png)


②使いたいDBとその所有者を確認し、
application.propertiesファイルに記載のDB接続情報とズレがないかを確認する。
```application.properties
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/sample
spring.datasource.username=postgres
spring.datasource.password=XXXXXXXX
```

今回は、usernameとpasswordの設定が誤っていたのでそこを修正したら、エラー解消しました。
同事象が起きた際には、aplication.propertiesファイルの設定内容に記載されているものが、正しい所有者のユーザー情報になっているかを確認しておくとよさそうです。


以上です。

# 参考記事
https://qiita.com/tom-sato/items/037b8f8cb4b326710f71

https://eng-entrance.com/postgresql-role
❯ rails g devise:installを実行したら


ログイン機能を実装しているところでインストールをおこなった
以下の表示が出てくる。
 ❯ rails g devise:install
Running via Spring preloader in process 
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================



===============================================================================

Depending on your application's configuration some manual setup may be required:

1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

     * Required for all applications. *


意味
環境ファイルにデフォルトのurlオプションが定義されていることを確認してください。以下は
     は、開発環境に適した default_url_options の例です。
     config/environments/development.rb で定義します。

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     本番環境では、:host にアプリケーションの実際のホストを設定する必要があります。



     * すべてのアプリケーションで必要です。*

2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"
     
     * Not required for API-only Applications *
意味

config/routes.rbでroot_urlを*something*に定義していることを確認します。
例えば

       ルートから "home#index"
     
     * APIのみのアプリケーションでは必要ありません。
     
     
3.
Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

     * Not required for API-only Applications *
    
意味
app/views/layouts/application.html.erb にフラッシュメッセージがあることを確認します。
     例えば

       <p class="notice"><%= notice %></p>のようにします。
       <p class="alert"><%= alert %></p> ※API専用アプリケーションでは不要です。

     * APIのみのアプリケーションでは必要ありません。

4.You can copy Devise views (for customization) to your app by running:

       rails g devise:views
       
     * Not required *

意味
実行することで、Deviseのビュー(カスタマイズ用)をアプリにコピーできます。

       rails g devise:views
       
     * 必須ではありません。
--------------

Depending on your application's configuration some manual setup may be required:

（あなたのアプリケーションの構成次第で、手動の設定が必要な場合がある。）　うーん、何が言いたいのかわからない。

特にmay beって突っ込みどころ満載だ。
1-4を全て行う必要があるのかないのか。
どっちだ。

https://qiita.com/MasatoraAtarashi/items/0e5e218481b06baf880c

これを参考に行えとターミナルは言っているのだろう。
apiを入れたければ1-4
それ以外なら1だけ行う
ってことで再度やってみる
【Rails】エラーメッセージや時刻表示を日本語化する。

# はじめに
デフォルトで英語表記になってしまうところが散見される。特にバリデーションをかけた時のエラーメッセージや、投稿した記事のタイムスタンプなどがよくある。
それを日本語化するため、実装した内容を記載していく。

# 環境
| No |    項目     |   内容    |
|---:|-------------|------------|
| 1  |      OS       |   Mac     |
| 2  |       Ruby      |   2.6.3   |
| 3  |       rails      |      6.0.4 |
# 実装
# 1. エラーメッセージを日本語化
[こちら](https://qiita.com/kents1002/items/509ea32715bb78c6d3e2)を参考にエラーメッセージの日本語化を目指す。
```config.rb
    # 以下を追記
    I18n.config.available_locales = :ja
    I18n.default_locale = :ja
```
config/locales/ja.ymlに[こちら](https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/ja.yml)のURLのコードをコピペすることで、基本的なエラーメッセージの日本語化をしてくれる。ここにない種類は日本語に変換してくれないので、自分で追加するか、HTML本文の方に表示するエラーメッセージを追加する。
私は後者の手段をとっている。
例
```ruby:post.rb
validates :image_top, :image_main, 
content_type: { in: %w[image/jpeg image/gif image/png], message: "画像ファイルを添付してください" }
```
次に自分が定義しているテーブルの日本語（ないし好きな表示させたいワード）をja.ymlに追加する。
```ja.yml
ja:
  activerecord:
    models:
      post: ポスト
      user: ユーザー
      comment: コメント
      staticpage: ホームページ
    attributes:
      post:
        title: タイトル
        content: 投稿文
        image_top: トップ画像
        image_main: 本文の画像
      user:
        name: 名前
        email: メールアドレス
        password: パスワード
        password_confirmation: 確認用パスワード
        remember_me: ログインを記憶
      comment:
        comment_content: コメントの内容
      staticpage:
        content: 内容
        name: 名前
        email: メールアドレス
・・・
```
これはラベルなどに反映される。
例（userモデル）
![スクリーンショット 2022-08-14 22.34.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2684787/b21a5743-bdd6-dfcc-82c7-cf064c3a131b.png)

```ruby:users/_form.html
<%= form_with(model: @user, local: true) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>

  <%= f.label :name %>
  <%= f.text_field :name, class: 'form-control', autofocus: true %>

  <%= f.label :email %>
  <%= f.email_field :email, class: 'form-control' %>

  <%= f.label :password %>
  <%= f.password_field :password, class: 'form-control' %>

  <%= f.label :password_confirmation %>
  <%= f.password_field :password_confirmation, class: 'form-control' %>

  <%= f.submit yield(:button_text), class: "btn btn-primary" %>
<% end %>
```
ラベルに一つずつ名前を与えなくても、ja.ymlで定義しているため、日本語に変換される。

# 2. 時刻表示を日本語化
**2022/8/15更新**
コメントでご指摘いただいた内容をもとに修正しました。
[【Rails】l(エル)メソッドを使用して時刻表示を日本語化rev1](https://qiita.com/vaza__ta/items/cdd1937a7f2e755d6e1a)
下記のやり方でも実装可能ですが、よりDRYにするなら、上記の方法をとるべきかと思います。

---
**l(エル)メソッドを使用しない実装方法**
[こちら](https://qiita.com/tomo_k09/items/e4f19947d35890500492)の記事を参考に時刻表示を日本語化を目指す。

```config/application.rb
config.time_zone = 'Tokyo'
```
config/initializers/time_formats.rbを作り、下記を記載する。
```config/initializers/time_formats.rb
Time::DATE_FORMATS[:datetime_jp] = '%Y年 %m月 %d日'
```
投稿のタイムスタンプを修正する。
```ruby:posts/show.html.erb
<%= post.created_at.to_s(:datetime_jp) %>
```
rails serverを立ち上げ直すと、時刻表示が日本語になる。
![スクリーンショット 2022-08-14 22.55.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2684787/319e7038-5bd3-1a7d-a704-a37c88437aad.png)

# おわりに
お疲れ様でした。
AWSのアクセスキーがファイルに含まれていたらエラーとしたい

## 目次
- [概要](#概要)
- [準備](#準備)
  - [git-secretsのインストール](#git-secretsのインストール)
  - [コマンドの確認](#コマンドの確認)
- [設定](#設定)
- [検証](#検証)
  - [AWSのアクセス情報を含むファイル作成](#awsのアクセス情報を含むファイル作成)
  - [ファイルの中身を表示](#ファイルの中身を表示)
  - [git secretsでファイルをスキャンしてみる](#git-secretsでファイルをスキャンしてみる)
- [参考](#参考)

## 概要

AWSを用いた開発を行なっていると、AWSのアクセスキーを用いてローカル環境で検証を行います。
しかし、検証後にそのままコミットして、AWSアクセスキーをGitリポジトリに混入させてしまうリスクがあります。
そこで、AWSのアクセスキーがファイルに含まれていたらエラーとする方法について検証しました。

## 準備

### git-secretsのインストール
```bash
$ brew update
$ brew install git-secrets
```

### コマンドの確認

```bash
$ which git-secrets
/usr/local/bin/git-secrets

$ git secrets
usage: git secrets --scan [-r|--recursive] [--cached] [--no-index] [--untracked] [<files>...]
```

インストールされていることを確認。

## 設定

```
git secrets --register-aws --global
OK
```

以下が追加されていることを確認

```~/.gitconfig
[secrets]
	providers = git secrets --aws-provider
	patterns = (A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}
	patterns = (\"|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)(\"|')?\\s*(:|=>|=)\\s*(\"|')?[A-Za-z0-9/\\+=]{40}(\"|')?
	patterns = (\"|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?(\"|')?\\s*(:|=>|=)\\s*(\"|')?[0-9]{4}\\-?[0-9]{4}\\-?[0-9]{4}(\"|')?
	allowed = AKIAIOSFODNN7EXAMPLE
	allowed = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```

allowedに値を指定すると、エラーならず、許容されます。
上記の値は以下URLのサンプルのキー情報です。

https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-access-keys-best-practices.html

## 検証

### AWSのアクセス情報を含むファイル作成
```bash
vi aws_credential.txt
```

### ファイルの中身を表示
```bash
$ cat aws_credential.txt 
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLo
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEo
```

### git secretsでファイルをスキャンしてみる
```bash
$ git secrets --scan --no-index
fatal: not a git repository (or any of the parent directories): .git
aws_credential.txt:3:aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEo

[ERROR] Matched one or more prohibited patterns

Possible mitigations:
- Mark false positives as allowed using: git config --add secrets.allowed ...
- Mark false positives as allowed by adding regular expressions to .gitallowed at repository's root directory
- List your configured patterns: git config --get-all secrets.patterns
- List your configured allowed patterns: git config --get-all secrets.allowed
- List your configured allowed patterns in .gitallowed at repository's root directory
- Use --no-verify if this is a one-time false positive
```

上記のように、エラーとなってくれました。

後は、これをhuskyと組み合わせてgitでcommit時に上記コマンドを実行するようにすればよさそうです。

huskyの使い方は以下でまとめているので、気になる方はどうぞです。

https://qiita.com/memomaruRey/items/de9e2f9e108ca8a27e61

## 参考

https://dev.classmethod.jp/articles/startup-git-secrets/
初めてIAMユーザーを追加したけどcsvをDLせずに閉じちゃった......そんなときは！

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779586/a99bc99a-9f6e-ea40-ea95-f77b7eb89066.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779586/01d6c7d0-eebe-f698-7609-94e09ade7823.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779586/ed05e2f8-1f57-05e2-de80-54186e3591c2.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2779586/afe33e14-3cad-6a79-d9f0-4882499a5bab.png)
Flutter on VScode

# はじめに
世はまさに大VScode時代ですね
自分はvimmerに憧れておりterminalで生活していますが
チーム開発となるとVScodeを使わざるを得ません
ということで、チーム開発flutter on VScodeの始め方です

**作業環境**
-device: thinkpad X1 carbon gen10
-smartphone: OPPO Reno3 A(android 11.0)
-CPU: intel(R) corei7-1260P
-GPU: intel(R) Iris(R) Xe Graphics
-RAM: 32GB
-SSD: 500GB
-Flutter: 3.0.5
-VScode: 1.68.1

# VScodeにflutter extention追加
VScodeサイドパネルのExtentionにて"flutter"を検索しinstallしましょう

# Flutter project作成
VScode上でF1を入力
Flutter: New Projectを入力
Applicationを選択
作業フォルダを配置するディレクトリを選択
作業フォルダ名を命名

# Android emurator作成
android studio起動
more action > Virtual Device Manager > Create virtual device選択
New hardware ProfileからOPPO Reno3 Aの画面サイズを設定: 6.44inch
andoroidのversionを選択しダウンロード: andoroid 11.0
以上でemuratorの完成です

# VScodeでemuratorを動かす
VScode右下のdevice to useを選択します
ポップアップの選択肢に先ほど作成したemuratorが表示されるので、そちらを選択
terminalを開いて`flutter run` commandを入力するとflutterプロジェクトが動きます
40歳事務職おじさんSQLめんどくさい→SQLはでかいファイルもさっくさく

40歳おじさんがSQLを勉強しているのですが、分析ならExcelでやればいいじゃん！なんでこんなめんどくさいことするの？っと思って学習していました

でも大事なことに気が付きました

<h2>10万件とかのビッグデータはExcelだとフリーズする

<b>Excelで開けばいいじゃん！→データが多すぎて開けない

だからSQLがあるのか！って気がつく

逆に言えば数百件ぐらいのでデータであれば
SELECT * FROM テーブル名 でデータを抽出してExcelで分析したほうが楽

<h2>SQLやPythonのpandasでデータ加工すれば早い

エクセルを開くのに時間がかかる、開かないほどのデータファイルなら、SQLで分析したり、pythonのpandasを使って操作したほうがさっくさくで早い

<h2>40歳おじさん気がつく！でも自分の部署そんなでかいファイルない

仕事で使えばさっくさくだ～ッと思ったけど、そんなでかいファイル扱わないんだよね

プライベートでスクレイピングして数万件のデータで遊んでるからそっちでは役に立つけれど。

python＋openpyxlでExcel自動化して仕事を楽にしようともいました
退屈な念仏はpythonにやらせよう

日本の仏教では、自身の往生などを目的として7日間の間に百万回念仏を唱える「百万遍念仏」があるそうです。

https://ja.wikipedia.org/wiki/%E7%99%BE%E4%B8%87%E9%81%8D%E5%BF%B5%E4%BB%8F

お経を唱えることに集中することで、煩悩から解放されたり、祈りが届いたりするのでしょう。

自分も人生の諸々に疲れ切っていたので、念仏を唱えて救われようと思ったのですが、そもそも念仏を唱える気力がないという問題にぶち当たりまして、pythonに代わりに念仏を唱えてもらうことにしました。

書いたコードはこちらです。

```nenbutsu.ipynb
Nenbutsu = '南無阿弥陀仏'
Hyakumanben_Nenbutsu = Nenbutsu * 1000000
print(Hyakumanben_Nenbutsu)
```

文字列型の「南無阿弥陀仏」と整数型の「1000000」の乗算が定義できることがポイントです。

（文字列型と整数型の足し算ー例えば「a+3」などーは定義されてない点は注意が必要です。）

![スクリーンショット 2022-08-14 21.41.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210818/e2417227-9e45-ed45-60ee-274b8f11f4a4.png)

いざ実行！と走らせたのですが、データ処理の限界が来たようで初回は唱えきれませんでした。

そこで、エラーメッセージをコピペしてググってヒットした以下の記事の通りに対策しました。

よしたくblog、Jupyter Notebook で IOPub data rate exceeded エラー

https://yoshitaku-jp.hatenablog.com/entry/2018/12/15/164849

まず、Macのターミナルで「jupyter notebook --generate-config」と打ちました。

次に、「Finder」の「移動」から「フォルダへ移動」を開き、以下のパスを打ちました。

「~/.jupyter/jupyter_notebook_config.py」

ファイルの探し方はAppleのサポートを参考にしました。

macOSユーザガイド、パス名を入力することでフォルダへ移動する

https://support.apple.com/ja-jp/guide/mac-help/mchlp1236/mac

![スクリーンショット 2022-08-14 21.42.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210818/7a1f444b-df69-16bb-c724-5429e7cfbbaa.png)

![スクリーンショット 2022-08-14 21.42.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210818/8d4d989d-9bef-63f2-84b4-b6908bd371aa.png)

![スクリーンショット 2022-08-14 21.42.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210818/fe58961a-fbad-b3eb-6441-fbc55837e960.png)

目的のファイル「~/.jupyter/jupyter_notebook_config.py」を見つけました。

ファイルを開いて、以下のように変更します。

変更前：#c.NotebookApp.iopub_data_rate_limit = 1000000

変更後：c.NotebookApp.iopub_data_rate_limit = 10000000

該当箇所は「command+f」で検索バーを開き、「rate_limit」と検索して探しました。

変更後にコメントアウトを消したときに余計なインデントを入れていると変更が反映されないので、空白は残らないように左に詰めて保存します。

![スクリーンショット 2022-08-14 22.23.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210818/fae3d07c-602c-9e5d-f95a-072eff080d90.png)

上の画像のように書き換えて保存したところで、改めてコードを実行すると、、、できました！

![スクリーンショット 2022-08-14 21.47.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210818/905b5e71-9357-8e41-6766-6035adf23f2d.png)

南無阿弥陀仏が下にひたすらスクロールし続けても表示され続けて気持ち悪くなってきますね。

これで自分は往生できそうです。皆さんも是非試してみてください。

お読みいただきありがとうございました。
便利ツール３選！

## TL;DR

使えそうなツールを3つ紹介します。

1. Python - [diagrams](https://github.com/mingrammer/diagrams)
1. Markdown - [Mermaid](https://mermaid-js.github.io/mermaid/#/)
1. Microsoft - [PowerToys](https://github.com/microsoft/PowerToys)

## 概要

エンジニアとして働いている中で、もっと早く知りたかったものを３つ紹介したいと思います。これらのものは作業の効率向上につながると思いますし、マスターしてしまえば見栄えにもなるかと思います！

ぜひ使ってみてください！

## 【1】 Pythonで簡単に構成図を！

AWSの構成図等の図を、pythonコードで描けるライブラリーがあります。これを使えばもっと簡単にアーキテクチャ図が描けますね！https://github.com/mingrammer/diagrams

### インストール

```shell
pip install diagrams
```

### サンプルコード

```sample.py
from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB

with Diagram("Grouped Workers", show=False, direction="TB"):
    ELB("lb") >> [EC2("worker1"),
                  EC2("worker2"),
                  EC2("worker3"),
                  EC2("worker4"),
                  EC2("worker5")] >> RDS("events")
```

### 出力

![dc099031-0e36-4085-87c2-2f84d6f85460.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290515/68c76b55-e44d-f130-2ff1-480a7470ac64.png)


## 【2】Markdownで簡単にGraphを！

☆エンジニアたるものはグラフを手で描くべからず！☆

Markdownがドキュメントの主流になりつつある中で、「Markdownでフローチャートとか簡単に描けたらいいのになぁ」と思ったら、なんと、もうできてると:超びっくりマーク:
Markdownの中に[Mermaid](https://mermaid-js.github.io/mermaid/#/)を埋め込むと、コードレベルで簡単にグラフをできます。

さらにVS Codeに拡張機能を追加すると効率が爆上げです！


### 事前準備

VS codeの拡張機能をインストール
https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid

### サンプルコード

```mermaid
flowchart TD
    A[Start] --> B{Is it?}
    B -- Yes --> C[OK]
    C --> D[Rethink]
    D --> B
    B -- No ----> E[End]
```

### 出力結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290515/0b78fb92-a7bf-1733-04af-f9fffd6a769d.png)

## 【3】PowerToys

MicrosoftがOSSで開発中のソフト、PowerToys 、を入れて効率向上！
利便性向上の機能を複数提供していますが、その中３つのもっと早く知りたっか機能を紹介したいと思います！

### 機能１: Awake

Awake 機能をオンにするだけでPCが起きったままになる！
もうPCが寝ることはなかろう。
（もちろんエンジニアたるもで、自前で実装できたが、Microsoftさんの方が安心ですねwww）

### 機能２：Color Picker
これを実行することで、今のマウスポインタがある場所のカラーコードを表示してくれます！
さらにピクセル単位で取得でき、フロント開発にもスーパー欲しかった機能でした。

![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290515/658de24b-d7e7-6fff-c25c-4809e840ca88.png)

### 機能３：Image Resizer

選択した画像を右クリックするだけ、簡単に画像の解像度を任意に変更できる！
さらに「元の縦横比に合わせる(Fit)」「引き延ばす(Stretch)」「幅に合わせる(Fill)」の機能が用意され、アイコンの作成などに活用できそうです！

![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290515/871a3a3b-5b13-f0b0-20c1-f88dcc967ff2.png)
karabainerを設定したのに反映されない件

### プライバシー設定に追加設定しないといけない

karabinerを起動すると、「プライバシー設定でkarabinerを許可してね、という文言が表示される。
そのときには、「入力監視」項目で「karabiner_observer」と「karabiner-EventViewer.app」が選択候補として上がる。
だが、この２つを許可しても、その後キーバインドを設定したとして、その設定が反映されない。
なんでだろう……と試行錯誤してたら、上記２つの他に「karabiner_grabber」を追加しないといけないらしい。

![スクリーンショット 2022-08-14 21.53.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400584/6a25e9d5-f602-f76d-04b3-205ca683a8df.png)

初回登録時には、この[karabiner_grabber」が表示されていないので陥りがちな落とし穴である。
これを追加するためには、「＋」ボタンを押下し、手動で指定する必要がある。
これの居場所は`/Library/Application Support/org.pqrs/Karabiner-Elements/bin`にある。
追加してあげるとキーバインドの設定が反映されているはず

### なんでこれに気づいたか？
 　初めて起動したときの「プライバシー設定でkarabinerを許可してね」の画像をよく見たら発見した……（赤矢印は元画像からあるものです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400584/753530ca-91c3-0f5c-b700-8d87e856944d.png)
javaScript_正規表現,search,replaceメソッドなど

```js
参考:
https://qiita.com/iLLviA/items/b6bf680cd2408edd050f

i	大文字小文字区別しない
g	すべてのものを検索
m	複数行検索
[abc]	[]内のものを検索
[0-9]	0-9の数字を検索


<body>
 <p id="test"></p>
 <button onclick="testReplace()">click me</button>
 <script>
  var stringTest = "tomorrow will be good";

  //　大文字小文字区別しないで検索
  var goodIndex = stringTest.search(/Good/i);
  var pTest = document.getElementById("test");
  pTest.innerHTML = "Goodのインデックスは" + goodIndex;

  function testReplace(){
   var newString = stringTest.replace(/tomorrow/i,"明日");
   pTest.innerHTML = newString;
 }
 </script>
</body>

```
floatとclearfixの使い方

# floatとclearfixの違い

ある要素の中で横並びのレイアウトを実現するために、floatをかけた要素の高さを親要素が認識しなくなることで、表示が崩れる場合がある。

### floatプロパティとは
要素に'right'や'left'といったように、値を設定すると要素を右・左寄せすることができる
また、floatは'浮く'という意味
例) float: 'left'; (左寄せ)

### clearixプロパティとは
floatプロパティに'right'や'left'を設定することで、要素が右寄せ左寄せになった要素に対して、回り込みを解除するプロパティ

# floatで要素を横並びにする

```index.html
<body>
    <div class="left"></div>
    <div class="right"></div>
    <div class="bottom"></div>
</body>
```
```style.css
.left {
  float: left;
  width: 100px;
  height: 100px;
  background-color: yellow;
}
.right {
  float: left;
  width: 200px;
  height: 200px;
  background-color: red;
}

.bottom {
  float: left;
  width: 300px;
  height: 300px;
  background-color: green;
}
```
以下のような表示になる(黄色、赤、緑が横並びになる)

![HTML ボックス.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/26192477-2182-b408-1c84-23fc6b764307.jpeg)

ここで、緑だけ'float: left;'を解除すると

![HTML float解除.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/77af9429-fbb9-bf70-24ea-10a1763c70b7.jpeg)


このように、黄色と赤色の下に緑色が回り込んでしまう。
この回り込みを解除して、黄色と赤色の下に表示するには、clearfixを使う。

# clearfixで回り込みを解除する

```index.html
<body>
  <div class="clearfix">
    <div class="left"></div>
    <div class="right"></div>
  </div>
  <div class="bottom"></div>
</body>
```

```style.css
.clearfix::after {
  content: "";
  display: block;
  clear: both;
}
.left {
  float: left;
  width: 100px;
  height: 100px;
  background-color: yellow;
}
.right {
  float: left;
  width: 200px;
  height: 200px;
  background-color: red;
}
.bottom {
  width: 300px;
  height: 300px;
  background-color: green;
}
```
上記のように、clearfixクラスを追加し、cssを記述すると下の画像のように、黄色と赤色の下に緑色がずれ込む。

![HTML clearfix.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/eedb00fc-fefc-f153-c17a-e82843405088.jpeg)

### clearfixクラス

```
.clearfix::after {
  content: "";
  display: block;
  clear: both;
}
```


::after
=> 擬似要素。選択した要素の最後に子要素が作られる

content: "";
=> ::beforeまたは::afterを指定する場合、必ずcontentを指定する必要があり,任意の文字列を指定することができる。
テキストや記号を擬似要素として挿入したい場合は、content内に記述し、要素や画像は、contentを空にする。

display: block;
=> コンテンツをまとめるブロック要素を指定

clear: both;
=> floatを解除する

# 参考

https://breezegroup.co.jp/202004/float-clearfix/

https://b-risk.jp/blog/2022/03/pseudo_elements/
Windows11にDockerをインストールしてみた②

<h4>はじめに</h4>
　Windows11にDockerをインストールしてみた①の続きです。<br>
　
 Dockerをインストールしてみたはいいが、アイコンをダブルクリックした後に開けなかったため、解決方法を記載してみました。<br>

 Windows11の操作が怪しい人、初心者の人がわかりやすいように細かくスクショをとってます。

***
 <h4>Dockerのインストール方法</h4><br>
 まだ、Dockerをインストールしていない方は、下記の記事を参考にインストールをお願いします。<br>

https://qiita.com/CatLogic_Blue/items/2f8484902b91f0617dbd

***
ディスクトップにアイコンが出てくるので、ダブルクリックしてDockerを起動しようとします。
以下のポップアップが出てくると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646863/7d43dfd5-4f76-0a8e-6ac3-0b39cb39d559.png)


右下の「I accept the terms」にチェックを入れると、下記のように「Accept」ボタンが活性になりボタンが押下できるようになります。ボタンを押下し、次の画面へ移りましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646863/eabaeb97-410d-c549-ab02-5b7dbb911854.png)

次の画面に移りましたら、以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646863/73a4ba89-8bb6-6573-75db-c301084183de.png)
しばらくすると、警告のポップアップが現れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646863/e8afbe14-24a3-1a88-8af5-87ec8e73f357.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646863/fbddf3fe-61aa-d01d-e69c-70b110048f5b.png)

どうやら、警告のポップアップにあるリンクをクリックし、指示に従ってカーネルアップデートをインストールする必要があるみたいです。
以下へ飛びます。

後は移動したページ通りに実施すればよいのです。（手順④まで実施する）
   
https://docs.microsoft.com/ja-jp/windows/wsl/install-manual#step-4---download-the-linux-kernel-update-package

 注意）【手順④】Linux カーネル更新プログラム パッケージをダウンロードする　までで大丈夫です。（今のところは）手順⑤以降を実施しなくても、無事に起動はできたので。

以下の参考にしたところでは、手順④までの実施する記事でした。

https://otona-life.com/2022/06/12/122957/

手順④まで実施し、PCを再起動します。
再起動後、Dockerのアイコンをダブルクリックすると、以下の画面が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646863/9b4a1f9f-e9ee-ea67-b1f6-c4fc81096503.png)

警告は出てこなくなりました。
「Start」ボタンは、チュートリアルなので、チュートリアルを実施したい方はボタン押下します。
　飛ばしたい方は、ボタン下の「Skip tutorial」のリンク文字をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646863/5e137337-4478-7a07-35af-b74739a11c42.png)

Dockerが無事に開けるようになりました。
お疲れ様でした。
素敵なDockerライフをお楽しみください。
xUnitでExceptionをテストする

# はじめに

xUnitを使用してユニットテストを書いていくと、Exceptionをキャッチするテストを書くことがあります。
これまで、Assert.Throws を使うことが多かったのですが、腑に落ちにくいところがありました。

というのも、基本的に自分はテストはAAA (Arrange, Act, Assert)に分けて書くようにしていたのですが、このAssert.Throwsは果たしてどこに入るものなのか？という疑問がありました。

たとえばこれまでよくこんな感じで書いていました。

```C#
[Fact]
public void CustomerTest()
{
    var exception = Assert.Throws<ArgumentException>(() => 
        CreateCustomer(customerId, customerName, email));
    Assert.Equal("名前が入力されていません", exception.Message);
}
```

# Assert.Throwsは AAA (Arange, Act, Assert) のどこに入る？
一般的にAAAの基本構造は以下のようなものです
```C#
[Fact]
public void CustomerTest(){
    // Arrange: 準備

    // Act: SUT(テスト対象)へのテストを実施

    // Assert: 結果の確認
}
```

では、Assert.Throwsは？
先ほどの例として挙げたコードを例にすると
```C#
[Fact]
public void CustomerTest()
{
    // Arrange
    string customerId = "id00001";
    string customerName = "";
    string email = "sample@example.com";

    // Act
    var exception = Assert.Throws<ArgumentException>(() => 
        CreateCustomer(customerId, customerName, email));

    // Assert
    Assert.Equal("名前が入力されていません", exception.Message);
}
```

つまり、Assert.ThrowsがActに記述されることになります。
でも、"Assert"と書いているので、もやもやするんです。気にならない人もいるとは思いますが、Actと書きながらAssertがあるというのが自分としては、なんだか気持ちが悪いです。

# Assert.ThrowsをAssertに書く方法
２つの方法を紹介させていただきます。
## 1. Actionを使用する
Actionを使って、メソッドだけをActに書き、Assert.Throwsの引数に使用するというやり方です。
こんな感じになります。
```C#
[Fact]
public void CustomerTest()
{
    // Arrange
    string customerId = "id00001";
    string customerName = "";
    string email = "sample@example.com";

    // Act
    void Action() => CreateCustomer(customerId, customerName, email);

    // Assert
    var exception = Assert.Throws<ArgumentException>(Action)
    Assert.Equal("名前が入力されていません", exception.Message);
}
```
こんな風に、ActにはAction()を使用して分離させます。
ActにAction、AssertにAssert.Throwsが書かれていることになるので、見た感じでも分かりやすいように思います。
ちなみに戻り値のある場合は以下のようにFunction()を使用すればいいです。
```C#
    // Act
    Customer Function() => CreateCustomer(customer);

    // Assert
    var exception = Assert.Throws<ArgumentException>(Function)
```

## 2. Record.Exceptionを使用する方法
もう一つの方法はAssert.Throwsに似ているのですが、Exceptionを先に指定しない方法です。
ちなみにRecordというのはRecord型のことではなく、XUnitのRecordクラスです。
こんな感じになります
```C#
[Fact]
public void CustomerTest()
{
    // Arrange
    string customerId = "id00001";
    string customerName = "";
    string email = "sample@example.com";

    // Act
    var exception = Record.Exception(() => {
        CreateCustomer(customerId, customerName, email);
    }

    // Assert
    Assert.Equal(typeof(ArgumentNullException), exception.GetType());
    Assert.Equal("名前が入力されていません", exception.Message);
}
```
Actはメソッドに集中し、Record.Exceptionで例外をキャッチして、Assertでその例外を確認するということができます。コードからも明確に例外を確認するテストであることが分かります。

# まとめ
いずれの場合でもテスト自体は成功しますが、テストは「何をテストしているのか明瞭である」ことが大切だと思います。
1つ目のActionの使用はパッと見は分かるのですが、ただメソッドの宣言だけで実際に実行しているのはAssert内となっています。それに対し2つ目のRecord.ExceptionはActで実行をしています。
そう思うと、最後のRecord.Excptionを使用する方法は、見た目も動作的にも一番しっくりくるように思いました。