OmniAICreator/Qiita-1.07M huggingface dataset:
ECRにdocker pushしてもLambdaが古いイメージを参照する

# 課題
Makefileを用いてECRにイメージをdocker pushした。
Lambdaはlatestタグのイメージを使用しており、新しいイメージがlatestタグを取得したにも関わらず、新しいイメージが使われなかった。

# code

```Makefile
PROFILE ?= default

ECR_URI := 123456789.dkr.ecr.ap-northeast-1.amazonaws.com
IMAGE_NAME=image-name
LAMBDA_FUNCTION_NAME=my-function

.PHONY: deploy
deploy: ecr_login
	docker build -t $(IMAGE_NAME):latest -f ./xxx/runtime/xxx/Dockerfile ./xxx/runtime --no-cache
	docker tag $(IMAGE_NAME):latest $(ECR_URI)/$(IMAGE_NAME):latest
	docker push $(ECR_URI)/$(IMAGE_NAME):latest
 
.PHONY: ecr_login
ecr_login:
	aws ecr get-login-password --profile $(PROFILE) --region ap-northeast-1 | docker login --username AWS --password-stdin $(ECR_URI)

```

# 問題点
ECRにイメージをpushしただけではLambdaが使用するイメージは更新されない。
明示的にLambdaの使用イメージを更新しなければならない。

>Lambda は、イメージタグを特定のイメージダイジェストに解決します。これは、関数のデプロイに使用されたイメージタグを Amazon ECR 内の新しいイメージを指すように変更しても、Lambda は新しいイメージを使用するように自動的に関数を更新しないことを意味します。新しいイメージを同じ Lambda 関数にデプロイするには、Amazon ECR のイメージタグが同じままであっても、update-function-code コマンドを使用する必要があります。

from: [コンテナイメージで Python Lambda 関数をデプロイする - AWS Lambda](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-image.html#python-image-clients)

# 解決法

Lambdaが新しいイメージを使用するようにLambda関数の更新が必要だった。次のコマンドをMakefileに追加する。

```sh
aws lambda update-function-code --profile $(PROFILE) --function-name $(LAMBDA_FUNCTION_NAME) --image-uri $(ECR_URI)/$(IMAGE_NAME):latest
```

Makefileは次のようになる。

```Makefile
PROFILE ?= default

ECR_URI := 123456789.dkr.ecr.ap-northeast-1.amazonaws.com
IMAGE_NAME=image-name
LAMBDA_FUNCTION_NAME=my-function

.PHONY: deploy
deploy: ecr_login
	docker build -t $(IMAGE_NAME):latest -f ./xxx/runtime/xxx/Dockerfile ./xxx/runtime --no-cache
	docker tag $(IMAGE_NAME):latest $(ECR_URI)/$(IMAGE_NAME):latest
	docker push $(ECR_URI)/$(IMAGE_NAME):latest
	aws lambda update-function-code --profile $(PROFILE) --function-name $(LAMBDA_FUNCTION_NAME) --image-uri $(ECR_URI)/$(IMAGE_NAME):latest

.PHONY: ecr_login
ecr_login:
	aws ecr get-login-password --profile $(PROFILE) --region ap-northeast-1 | docker login --username AWS --password-stdin $(ECR_URI)

```
うちのPC紹介：アプライド i5-13500君

うちのPCのスペックとかを紹介します。

# 購入経緯
サーバ用マシンが欲しかったので、
アプライドに見に行ったところ、
割とコスパ良かったので購入しました。

# i5-13500君
## 用途
デスクトップサーバ用途で利用しています。
カスタマイズしてVM用マシンとしています。
開発や検証用途で利用しています。

## 公式ページ（販売会社）
・探し中

## スペック
・ASUS TUF Dash F15 FX517ZM (FX517ZM-I5R3060BEC)
・CPU：20x 13th Gen Intel(R) Core(TM) i5-13500
・メモリ：96GB（DDR4）
　・4枚
 　　・32GB×2
　　・16GB×2
・SSD：1TB（NVMe）
・GPU：TU106 [GeForce RTX 2070]
・OS：Ubuntu 22.04 LTS
・モットー：コスパ重視購入でGPUは使いまわし後付け

## カスタマイズ経歴
・SSD変更
　デフォルトのSSDを乾燥しました → WD Blue SN570 1TB
・GPU追加
　GPUを追加しました。→ TU106 [GeForce RTX 2070]
・OS入れ替え
　OSをUbuntu22.04にしました。

# 用途
・購入：2024年
・メインサーバ（開発環境）：2024年6月～

# その他
## 公開記事
ベンチマーク（実施予定）

## このマシン関連で検証した記事
・Ubuntu22.04+KVMでGPUパススルーをするときのメモ
https://qiita.com/kit/items/0817dd7389d7abfd7424
・Fugaku-LLMをCPUパソコンで動かしてみた ～CPUでもFugaku-LLMは動くのか！？～
https://qiita.com/kit/items/02c8af51ac181f02fd18
・GPUも使ってFugaku-LLMを動かしてみた ～古めのGPUサポートで動かしてみた～
https://qiita.com/kit/items/73572c0b67ef6cb17ee3
ReactでStoryBookを利用する(Dialogを呼び出し)

## はじめに
前回までの続きです。今回はStoryBookでDialogを呼び出す事を試してみたいと思います。

## 成果物
![dialog_sb.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/75c958e3-707a-9b2b-2a41-8132fbac8dee.gif)


## ソースコード
```tsx:src/components/Button.tsx
import type React from "react";
import { useState } from "react";
import Button from "@mui/material/Button";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";

type Props = {
	label: string;
};

const MyButton: React.FC<Props> = ({ label }) => {
	const [open, setOpen] = useState(false);

	const handleClickOpen = () => {
		setOpen(true);
	};

	const handleClose = () => {
		setOpen(false);
	};

	return (
		<>
			<Button variant="contained" onClick={handleClickOpen}>
				{label}
			</Button>
			<Dialog open={open} onClose={handleClose}>
				<DialogTitle>Dialog Title</DialogTitle>
				<DialogContent>
					<DialogContentText>This is a simple dialog.</DialogContentText>
				</DialogContent>
				<DialogActions>
					<Button onClick={handleClose}>Close</Button>
				</DialogActions>
			</Dialog>
		</>
	);
};

export default MyButton;
```

```tsx:src/components/Button.stories.tsx
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import MyButton from "./Button";

export default {
	title: "Example/Button",
	component: MyButton,
} as Meta<typeof MyButton>;

type Story = StoryObj<typeof MyButton>;

export const Primary: Story = {
	args: {
		label: "Open Dialog",
	},
};
```

## リファクタリング
```tsx:src/components/Button.tsx
import type React from "react";
import { useState } from "react";
import Button from "@mui/material/Button";
import MyDialog from "./MyDialog";

type Props = {
	label: string;
};

const MyButton: React.FC<Props> = ({ label }) => {
	const [open, setOpen] = useState(false);

	const handleClickOpen = () => {
		setOpen(true);
	};

	const handleClose = () => {
		setOpen(false);
	};

	return (
		<>
			<Button variant="contained" onClick={handleClickOpen}>
				{label}
			</Button>
			<MyDialog open={open} onClose={handleClose} />
		</>
	);
};

export default MyButton;
```

```tsx:src/components/MyDialog.tsx
import type React from "react";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";
import Button from "@mui/material/Button";

type Props = {
	open: boolean;
	onClose: () => void;
};

const MyDialog: React.FC<Props> = ({ open, onClose }) => {
	return (
		<Dialog open={open} onClose={onClose}>
			<DialogTitle>Dialog Title</DialogTitle>
			<DialogContent>
				<DialogContentText>This is a simple dialog.</DialogContentText>
			</DialogContent>
			<DialogActions>
				<Button onClick={onClose}>Close</Button>
			</DialogActions>
		</Dialog>
	);
};

export default MyDialog;
```
ros2 topic ***, ros2 node *** などのros2コマンドが反応しなくなったときの解決法

お疲れ様です。秋並です。

ros2を使っていてデバッグのために、 `ros2 topic` や `ros2 node` などのコマンドを使うことがありますが、しばらく使っているとこれらのコマンドが反応しなくなる時があります。

再起動をすれば基本的には治るのですが、毎回再起動するのは面倒なので調べてみたところ解決法が見つかりました。

<br>

具体的には、以下コマンドでros2 daemonを再起動すると、再度ros2コマンドが機能するようになります。

```bash
ros2 daemon start
```

```bash
ros2 daemon stop
```

```bash
ros2 daemon start
```

# 参考サイト

https://github.com/ros2/ros2cli/issues/702
Drupalの名前の由来ってなぁに？

Drupalの創設者であるDries Buytaert氏が学生時代に構築したニュースサイトのドメイン名に「dorp.org」を検討したそうです。

> "Dorp" is the Dutch word for "village," so it fit the small community they'd started.

訳："Dorp"はオランダ語で「村」を意味する。彼らが始めた小さなコミュニティーにぴったり。

ただ「dorp」を「drop」と間違えて入力したそう。それが drop.org の始まりだそうです。

「drop」（水滴・滴）という言葉にちなんで、Dries氏はこのソフトウェアを「drupal」と名付け、正式にリリースしたそう。

## 所感
入力間違いから生まれた名前だったんですね。
記事にするにあたって公式が出している情報を調査したんですが、思ったより経緯に関する記載が少ないなと思いました。

## 公式
https://www.drupal.org/about/history
tarファイルの分割

tarファイルの分割方法は以下コマンドで実施可能です。以下コマンドでは100MB単位で分割できます。
```
split-b 100M file.tar "file.tar.part-"
```

マージは以下コマンドで可能です。
```
cat file.tar.part-* > file.tar
```
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（54/100）

【54日目】
トピック 6：SAPS/4HANAの需要管理（5/5）

≪問題54≫
プロジェクトチームは、ディスクリート製造で戦略的な品目に対して受注生産計画方針を適用することを決定しました。この決定はどのような影響を持ちますか。
（３つ選択）
□受注生産在庫および所要量の削減が出荷/納入時に発生する。
□受注を保存するには、利用可能在庫（ATP）確認を実施する必要がある。
□個別受注在庫には保管場所MRPエリアが必要になる。
□受注参照の製造指図が生成される。
□正味所要量計算は、受注ごとに個別に実行される。

≪解答≫
■受注生産在庫および所要量の削減が出荷/納入時に発生する。
□受注を保存するには、利用可能在庫（ATP）確認を実施する必要がある。
□個別受注在庫には保管場所MRPエリアが必要になる。
■受注参照の製造指図が生成される。
■正味所要量計算は、受注ごとに個別に実行される。

≪解説≫
◆受注生産計画の特徴は以下のとおりです。
（1）正味所要量計算は受注ごとに個別に実行されます。受注間で在庫を交換することはできません。
（2）計画手配は受注を参照して登録され、個別の得意先セグメントで管理されます。受注へのこの直接参照は製造指図でも保持されます。
（3）加工費および調達費用は、決済指図またはプロジェクト内のそれぞれの受注専用に受注明細レベルで管理されます。
（4）所要量削減（受注）および受注在庫の削減は、納入時に発生します。
AWS SOA-C02 合格体験記

## はじめに
先日SOAの試験を受けてきて合格できたので、
簡単に勉強した内容などを書いてみます。

## 前提
- AWSの業務利用はほぼなし(VPCフローログ見るくらい)
- CLF、SAAは取得済みのためぼんやりサービスの概要がわかる

## 試験のスコア
813点

## 学習期間
1か月(大体30時間くらい)

## 学習内容
- AWS公式試験ガイド
- AWS Skill Builder Exam Prep
- [WEB問題集(CloudTech)](https://kws-cloud-tech.com/)
- [Udemy問題集](https://www.udemy.com/course/soa-c02aws-sysops-2024/?couponCode=ST9MT71624)
- [参考書](https://amzn.asia/d/04GSRpKf)

私がやった学習順序ですが、
①AWS公式試験ガイド
②Udemy問題集
③WEB問題集
④AWS Skill Builder Exam Prep
⑤参考書
となります。

結果的に言えば、この順序でも問題なかったかなーという印象です。

まずは、AWS公式試験ガイドでサービスを確認し、
Excelにこんな感じでひたすらサービスの概要をまとめていきました。
(途中でやめましたが…)
![スクリーンショット 2024-07-08 202356.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3776083/f1e2fada-6a4e-0968-8af5-4ccb86b72aee.png)

ここで大事なのは、試験対象になっているサービスが、
どのような運用で使えるのかをイメージできるようにしておく。ということです。

例えば、cloudwatchのアラームを契機としたSNSでの通知など、
サービスを組み合わせて何ができるかというのを具体的にイメージできるようになると理解度が高まります。


次は、ひたすら問題集を解いていっただけなので、中身の話は割愛します。
個人的にはサンプル問題を解くなら[CloudTech](https://kws-cloud-tech.com/)がおすすめです。
180問もサンプル問題が提供されており、1問ごとに回答・解説が出てくるので、不正解の部分や曖昧だった部分のフィードバックがすぐに行えます。
正解しても解説をきちんと読んでユースケースを理解しておくと良いです。

解説は丁寧でわかりやすかったので、下手に直訳版のUdemyを買ったりするよりはいいのかなと思います。
Udemyはなくてもよかったかなと思いました。



問題集が終わった後は、知識を補填しておきたいなと思ったサービスを参考書で学習する流れにしました。
好みの問題ですが、もっと詳しく知りたいのであれば、
[BlackBelt](https://aws.amazon.com/jp/events/aws-event-resource/archive/?cards.sort-by=item.additionalFields.SortDate&cards.sort-order=desc&awsf.tech-category=*all)や[AWSサービス別ドキュメント](https://docs.aws.amazon.com/?nc2=h_ql_doc_do)でもいいかなと思います。

## 感想
SAAとかなり試験範囲が被っていることもあって、
個人的にはそんなに難易度は高くない印象でした。
SAA合格できた人であれば、ある程度簡単に突破できるかなと思います。

## 終わりに
次はDVAの取得目指して頑張ります。
SAAの合格体験記も近々書いてみます。
ReactでStoryBookを使う

## はじめに
表題通り、ReactでStoryBookを使います。
コンポーネント単位で確認できる方が開発効率上がるので利用してみました！！

## 成果物
![story_book.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/75ecf6bc-5194-a1a9-41ab-c22e8ae1b07c.gif)

## 準備

```shell:プロジェクトを作成する
yarn create react-app my-storybook-app --template typescript
npx sb init 
yarn add @emotion/react @emotion/styled
```

:::note info
story bookのプロジェクトを作成します。
:::

## ソースコード

```shell:ディレクトリ構成
~/develop/my-storybook-app (master)$ tree src 
src
├── components
│   ├── Button.stories.tsx
│   └── Button.tsx
```

```tsx:src/components/Button.tsx
import type React from "react";
import Button from "@mui/material/Button";

type Props = {
	label: string;
	onClick: () => void;
};

const MyButton: React.FC<Props> = ({ label, onClick }) => {
	return (
		<Button variant="contained" onClick={onClick}>
			{label}
		</Button>
	);
};

export default MyButton;
```

```tsx:src/components/Button.stories.tsx
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import MyButton from "./Button";

export default {
	title: "Example/Button",
	component: MyButton,
} as Meta<typeof MyButton>;

type Story = StoryObj<typeof MyButton>;

const Template: Story = {
	render: (args) => <MyButton {...args} />,
};

export const Primary = {
	...Template,
	args: {
		label: "Button",
		onClick: () => alert("Button clicked!"),
	},
};
```


## リファクタリング
Dialogのみでテストできる方がいいので、それだけでテストできるようにしてみます。

![dialog_only.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/94685fc7-a0d0-e1e2-ece4-bd769a114658.gif)

```tsx:src/components/MyDialog.tsx
import type React from "react";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";
import Button from "@mui/material/Button";

type Props = {
	open: boolean;
	onClose: () => void;
};

const MyDialog: React.FC<Props> = ({ open, onClose }) => {
	return (
		<Dialog open={open} onClose={onClose}>
			<DialogTitle>Dialog Title</DialogTitle>
			<DialogContent>
				<DialogContentText>This is a simple dialog.</DialogContentText>
			</DialogContent>
			<DialogActions>
				<Button onClick={onClose}>Close</Button>
			</DialogActions>
		</Dialog>
	);
};

export default MyDialog;
```

```tsx:src/components/MyDialog.stories.tsx
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import MyDialog from "./MyDialog";

const meta: Meta<typeof MyDialog> = {
	title: "Example/MyDialog",
	component: MyDialog,
	args: {
		open: true, // ダイアログを開いた状態に設定
		onClose: () => alert("Dialog closed!"), // ダイアログを閉じるアクションを設定
	},
};

export default meta;

type Story = StoryObj<typeof MyDialog>;

export const Primary: Story = {};
```
Excel VBA セル結合と戦うためのコード

## いまだにそんなExcelファイルがあるんですかとか言わないでください

業務効率化の目的でもらった社内ファイルがゴリゴリにセル結合していました。
とりあえずデータベースとして使えるようにデータ成形をしようと思います。
全部で4,000行弱あったので、手作業でできるわけがないのでVBAでやりました。

かなりデフォルメしていますが、こんな感じの表が4,000行くらい続いています。
![セル結合.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/8c7a477d-3e66-879c-fdb8-391145c5cad6.png)

ここから、セル結合を解除して、B列を埋めていきます。

結合解除はB列を選択して手動で
![セル結合2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/e6973264-a3de-43c5-a01b-ecb9c5a51502.png)

結合解除後
B列がスカスカですね。このままでは、まともなデータベースとして使えないので、ここからVBAを書いて一気に仕上げます。
![セル結合4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/15688132-0ded-30bd-5dea-101ab7246b03.png)

```vb
Sub remakedata()

  Dim i As Long
  Dim LastRow As Long
  Dim ws As Worksheet
  
  Set ws = ThisWorkbook.Sheets("Sheet1") 'シート名を変数に格納
  LastRow = ws.Cells(Rows.Count, 3).End(xlUp).Row 'C列の最終行
  
  For i = 4 To LastRow '4行目から最終行までループ
  
    If ws.Cells(i, 2) = "" Then 'B4セルから下が空白なら
       ws.Cells(i, 2) = ws.Cells(i - 1, 2) 'ひとつ上のセルをコピー
    End If
  
  Next i
  
End Sub

```

実行結果
![セル結合3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/be634b67-b0c2-cdf9-42b6-bc0e909cfb8f.png)

実際のファイルでは体感でだいたい3～5分くらいかかりました。メモリ8Gのパソコンなので、もっとスペックの高いパソコンならもっと実行速度は速くなると思います。
AIがブランチ名を提案！GitHub/GitLabのブランチ名を一発生成するChrome拡張

前に、OpenAI APIを活用してIssueの内容から適切なブランチ名を自動生成するGitLab向けChrome拡張を作りました。

https://qiita.com/owayo/items/34a855ccfb90c96d729c

最近、GitHubのプロジェクトに関わるようになったので、GitHubでも動くように改良しました。

## ダウンロード

https://chromewebstore.google.com/detail/lbfkhiichdmakpghanpjjbicohannpcf?authuser=0&hl=ja

EdgeやArcでも動くと思います。

## しくみ
GitHubのIssueの、**Create branch**をクリックすると、ブランチ名を入力するモーダルダイアログが表示されます

![スクリーンショット 2024-07-08 19.31.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741957/05fbe1c9-711f-c774-2528-b26cbfe12f00.png)

ダイアログの表示をMutationObserver[^1]でフックして、ブランチ名作成のダイアログを表示させています。

![スクリーンショット 2024-07-08 19.02.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741957/50cf7841-ed65-3bf6-abee-ea1d0e82ede6.png)

Issueのタイトルから自動生成する場合は、**自動生成**ボタンをクリックします。
クリックするとIssueのタイトルと設定画面で設定したプロンプトをOpenAI APIに渡して、ブランチ名の候補を作ります。

![スクリーンショット 2024-07-08 19.36.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741957/b51d1ef0-8259-df53-1427-0fe4074827bb.png)

OpenAI APIのレスポンスをもとにブランチ名の候補がリストアップされます。
一覧から好みのものをクリックするとブランチ名に反映されます。

![スクリーンショット 2024-07-08 19.37.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741957/45ec4285-a672-ddd5-ff04-2204e6b67ae6.png)

## 設定

ブランチ名のプレフィックスや、プロンプトは拡張のオプション画面から設定できます。

![スクリーンショット 2024-07-08 19.42.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741957/576e03f7-3e8c-7dda-8236-0e758c017d65.png)

## まとめ
このChrome拡張機能は、チーム開発におけるブランチ命名の一貫性を保つのに役立ち、ブランチ名を一発生成できるので作業効率を向上させることができると思います。
個人的にはかなり重宝しています、がインストール数がいまいち伸びないという・・・。


[^1]: https://developer.mozilla.org/ja/docs/Web/API/MutationObserver
[AWS #16] ELB

<!--
 <font color="c00000"></font> 赤
-->
## はじめに
こんにちは
今回もコンピューティングサービス分野である **<font color="c00000">「ELB」</font>** について紹介したいと思います。

…の前に、ELBの前提知識となる　**<font color="c00000">「ロードバランサ」</font>** について軽く紹介いたします。
## ロードバランサ
「ロードバランサ」とは、その名の通りシステム負荷の **「バランス」** を取るために処理を **「分散」** させるものです。
![AWS16_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/4535bb02-5c3c-bb51-fb60-a9f846d05636.png)
上の図の例では、3台のサーバーの前に「ロードバランサ」を置くことで、ロードバランサが処理を3台に割り振ることができます。サーバー3台での処理が可能となり、**処理速度の向上、高可用性、耐障害性**が見込まれます。

:::note info
ロードは **「負荷」** を、バランサは **「バランス」** を指します。
:::

## ELB
ELBとは **「Elastic Load Balancing」** の略称で、同じ構成を持った2つのEC2インスタンスを別々のアベイラビリティゾーンに配置することができます。そしてELBはその2つのEC2インスタンスに、ユーザーからの**リクエストトラフィックを分散**させます。
![AWS16_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/1907e7a3-82d8-448a-1ac4-49d168a0bf62.png)
上図のように、複数のAZにまたがりシステムを構築することでAZが発生した場合でも、システムを稼働することができます。これにより、**高可用性や耐障害性を向上させる**ことができます。

:::note info
EC2インスタンスの**可用性、耐障害性を<font color="c00000">高めるため**にELBを使用することができます
:::

### ALB
ALBは**Application Load Balancer**の略称です。
「HTTP」「HTTPS」プロトコルのレイヤー7を負荷分散するロードバランサで、**「Webアプリケーション」** によく利用されています。

### NLB
NLBは**Network Load Balancer**の略称です。
TCPやUDPのレイヤー4で動作します。ALBとは異なり、静的なIPアドレスをみるので、ALBのような細かい振り分けはできません。しかし、**1秒あたりに「数百万」のリクエストを処理** することができます。

### CLB
CLBは**Classic Load Balancer**の略称です。
ALBとNLBが**リリースされる前のロードバランサ**です。
現在は、CLBを使用せずにALB、NLBを使用する事が推奨されます。

## おわりに
今回のちょっとしたまとめになります。

:::note info
ELBとはAWSが提供している **「ロードバランサ」** です
:::
:::note info
ELBには **「ALB」「NLB」「CLB」** の3つのタイプがあります
:::

**サーバの負荷（Load）を低減させる**ために、外部からのリクエストを複数サーバに振り分けし、**負荷分散をするロードバランサ**だということが理解できました。

最後までお読みいただきありがとうございました！
>日頃より活用している参考書です。
>> **「参考書」**
[AWS認定クラウドプラクティショナー改定第3版](https://x.gd/19i6N)
>
> **「AWS公式サイト」**
[Elastic Load Balancing](https://aws.amazon.com/jp/elasticloadbalancing/)
>
> **「参考元」**
[AWSのELBとは？](https://cloudnavi.nhn-techorus.com/archives/3640)
>
> **「Youtube」**
[【CLF-C02：AWSクラウドプラクティショナー】第20回 ELB (クラウドテクノロジーとサービス分野)](https://x.gd/m8yNY)
【2024年版】うちのPC環境まとめ（適宜更新）

この記事は、うちのPC環境まとめです。
よく、PCのスペックとか環境とかわからなくなるので個人用のメモです。
2024年の環境は適宜この記事に更新予定。


# 所有PCリスト

## 稼働中
・[i5-12450H君（デスクノート）](https://qiita.com/kit/items/5b73db3da7790a197306)
・[i5-13500君（デスクトップ）](https://qiita.com/kit/items/ddd1e09d590f7a92dc01)
・[初代GPDWIN：Z8750君（ウルトラモバイルPC）](https://qiita.com/kit/items/9ff19ed0bfd315a0d9e4)

## 非稼働中
・デュアルNIC君
・手のひらPC君
・RaspberryPI君

## 引退
・[デスクノート i7-7700HQ君](https://qiita.com/kit/items/090239c6a0b2a990eab6)

# それぞれのスペック・用途など

## i5-12450H君
### 解説
今のメイン利用ノートマシン君です。
### 関連記事
・スペック：https://qiita.com/kit/items/5b73db3da7790a197306
・ベンチマーク：https://qiita.com/kit/items/c7d4e562c13595012a6f
・SSD換装：https://qiita.com/kit/items/0d4a284c5a6364d7d602


## デスクトップ i5-13500君
### 解説
今のサーバ利用デスクトップ君です。
### 関連記事
・スペック：https://qiita.com/kit/items/ddd1e09d590f7a92dc01



## デスクノート i7-7700HQ君：引退
お友達の学生さんにあげました。
マインクラフトサーバとかゲームとか用途で稼働中とのことです。
### 関連記事
・スペック：https://qiita.com/kit/items/090239c6a0b2a990eab6
・ベンチマーク：https://qiita.com/kit/items/0d57a3433a2e44062d3a
【Next.js】use clientとuse serverの違いについて詳しく解説

## はじめに
今回は、Next.jsで追加されたuse clientとuse serverの違いについて説明していきます！

## 基本内容
Next.jsはReactのフレームワークの一つであり、サーバーサイドレンダリング（SSR）や静的サイト生成（SSG）をサポートしています。

## use clientとは
use clientは、クライアントサイドでのみ実行されるコードを指定するために使用されます。例えば、useStateなどのReactフックはuseClientコンポーネント内でしか使用できません。デフォルトでは、Next.jsのファイルはサーバーコンポーネントとして認識されているため、以下のように書くとエラーが発生します。

```typescript
import { useState } from 'react';

export const Test = () => {
  const [count, setCount] = useState(false);
  return(
    <>
        <div>カウント:{count}</div>
    </>
  
  )
}
```
この場合、ファイルの先頭に"use client";を追加して、クライアントコンポーネントであることを明示する必要があります。
```typescript
"use client";
import { useState } from 'react';

export const Test = () => {
  const [count, setCount] = useState(false);
  return(
    <>
        <div>カウント:{count}</div>
    </>
  
  )
}
```
従来のNext.jsでは、すべてのファイルがクライアントコンポーネントとして認識され、サーバーサイドのコードはバックエンドに分離されていました。しかし、Next.js 13ではこの点が変更され、より柔軟なフルスタック開発が可能になりました。

## use serverとは
use serverは、サーバーサイドでのみ実行されるコードを指定するために使用されます。
use serverの特徴は、フロントエンドのコード内でサーバーサイドの処理を記述できることです。これにより、Next.jsだけでフルスタック開発を完結させることが可能です。
メリット、デメリットは以下の通りになります。

### メリット
①APIを叩く必要がない
　従来は、フロントエンド側でAPIを呼び出し、サーバー側でデータを処理していました。しかし、Next.js内でサーバーサイドのコードを書くことで、APIエンドポイントを作成する必要がなくなります。
 
②直接ブラウザ側でPrisma（データベース）の操作が可能
　クライアントサイドから直接データベースとやり取りできるため、データフェッチや操作がシンプルになります。
 
③フォームタグのactionイベントは、JavaScript環境がなくても動作
　JavaScriptが無効な状態でも、HTMLのフォーム送信が正常に動作します。これは、クライアントとサーバー間のHTML要素が返される際に、JavaScriptのイベントハンドラが有効になる前でも、actionイベントがHTMLとして自動的に動作するためです。

### デメリット

①役割の曖昧さ
　以前はフロントエンドとバックエンドで明確に分離されていた役割が、クライアント側でサーバーの処理を書くことで曖昧になり、従来のWeb開発のスタイルに逆戻りしているように感じます。

 ## まとめ
 use clientとuse serverは、それぞれクライアントサイドとサーバーサイドでの動作を制御するための重要なフックです。これらを適切に使い分けることで、パフォーマンスの向上やSEO対策、ユーザー体験の向上を図ることができます。Next.jsを活用して、効率的なフルスタック開発を実現しましょう！
「完成の定義」を活用して、働きやすくしていく

## はじめに

◆この記事は何？
アジャイル開発やスクラムで活用される「完成の定義」についてサンプルや作成のコツを紹介する記事です。

◆対象は？
エンジニア

◆この記事のねらい
「完成の定義」を活用して後戻りを少なくする

## 先に結論
- 「完成の定義」とは、開発が完了したかを判断する基準
- 「完成の定義」はチームによって更新され続ける
- 「完成の定義」があれば、共通認識ができて、後戻りを減らせる

## 「完成の定義」とは

「完成の定義」は開発完了の判断基準です。
開発完了のチェックリストともいえます。

書籍[『SCRUM BOOT CAMP THE BOOK』](https://amzn.asia/d/0h7ElnNu)では、「品質基準」とも言及されています

> 完成の定義は、品質基準と言い換えることもできます。

開発を始める前にチームで合意します。

## 「完成の定義」をつくる理由

「完成の定義」をつくると、チームで共通認識が得られます。

アジャイル開発では、スプリント終了時に完成し正常動作する必要があります。
そのため、プロダクトオーナーと開発チームは「完成」の基準を共有する必要があります。

その結果、「完成の定義」があることで、後戻りを減らすことができます。

## 「完成の定義」のサンプル

書籍[『MORE EFFECTIVE AGILE』](https://amzn.asia/d/0bYYWmSI)で紹介されている「完成の定義」の例です。

> コードレビューを通過している
> 静的コード解析を通過している
> ユニットテストがエラーなしで完了している
> ユニットテストによるステートメントカバレッジが70%である
> システムテストと結合テストが完了している
> 自動化した非機能テストがエラーなしで完了している
> ビルド時にエラーや警告が出ていない
> パブリックAPIが全て文書化されている

機能だけでなく、テスト、非機能、ドキュメントなどにも言及されます。

このようなチェックリストがないと、「非機能要件未達で再作業」といった後戻りが増える可能性があります。

## 「完成の定義」をつくるコツ

「完成の定義」は、チームごとに独自に作成されます。

「完成の定義」を作成する際に次のことを気をつけます。

- 更新し続ける前提にする
- 量が多いときは分ける
    - 量が多すぎると参照しなくなるため
- 活動ではなくエビデンスを示す
    - 例：「コードレビューが完了」ではなく「コードがレビューを通過」
    - より客観性が向上するため

そのときの開発チームにとってより良い共通認識をつくり続けていきます。

## おわりに

この記事では、「完成の定義」について紹介しました。

アジャイル開発・スクラムに限らずに活用できる概念です。

「完成の定義」を活用して、後戻りを減らし、働きやすくなれば幸いです。

## 参考

書籍[『MORE EFFECTIVE AGILE』](https://amzn.asia/d/0bYYWmSI)

書籍[『SCRUM BOOT CAMP THE BOOK』](https://amzn.asia/d/0h7ElnNu)
Laravelで最速にAPIサーバーを作成する（３ステップ）

# 概要
LaravelでAPIサーバーを作成する際の要点をこの記事にまとめる。
以下のように実装すれば、主要観点を最短で実装できないか？と思う。

# ① routes/api.php にPATHを設定
```routes/api.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PlayerController;

~

Route::prefix('player')->group(function () {
    Route::get('/', [PlayerController::class, 'index']);
    Route::get('/{id}', [PlayerController::class, 'detail'])->where('id', '[0-9]+');
    Route::post('/', [PlayerController::class, 'insert']);
    Route::patch('/{id}', [PlayerController::class, 'update'])->where('id', '[0-9]+');
    Route::get('/search', [PlayerController::class, 'search']);
}
```

この時URIは `api/player/...` となることは、以下のコマンドでも確認できる。
`php artisan route:list`


# ②コントローラにAPIサーバの機構を実装
```App\Http\Controllers\PlayerController.php
use App\Models\Player;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

~

public function index(): JsonResponse
{
    $player = Player::all();
    return response()->json($player, options: JSON_UNESCAPED_UNICODE);
}

public function detail(int $id): JsonResponse
{
    $player = Player::find($id);
    return response()->json($player, options: JSON_UNESCAPED_UNICODE);
}

public function insert(Request $request): JsonResponse
{
    $createdRecord = Player::create($request->all());
    return response()->json($createdRecord, 201, options: JSON_UNESCAPED_UNICODE);
}

public function update(int $id, Request $request): JsonResponse
{
    $player = Player::where(['id' => $id]);
    $updateResult = $player->update($request->except('id')) ? 'success' : 'failure';
    return response()->json(['result' => $updateResult]);
}

public function search(Request $request): JsonResponse
{
    $players = Player::findBySearchRequest($request);
    return response()->json($players, options: JSON_UNESCAPED_UNICODE);
}

```

# ③モデルにDBとのやり取りのロジックを書く
```App\Http\Models\Player.php

static public function findBySearchRequest(Request $request)
{
    // 検索ロジックを書く（個別の状況によると思うので今回は割愛）
    return $players;
}

```

以上で、完成である。

# 補足
## APIのテストについて
簡易なGETメソッドのテストならURLを以下のようにすれば良い。
`/search?text=テスト&age=20`

POST、PUTCHなどのメソッドはじめ、詳細にテストしたい場合は、以下のようなツールなどを使うのが良いと思います。

https://apidog.com/jp/

---
記事をお読みいただき、ありがとうございました！
もし参考になったと感じましたら、「いいね」や共有など頂けたら嬉しく思います！
何卒よろしくお願い致します！
テキストを話してくれるAI技術が今後注目されていく理由について

# はじめに

テキストを話してくれるAI技術、つまりテキスト読み上げや音声合成技術は、近年急速に進化を遂げています。
その注目度はますます高まり、今後もさらに重要な技術となることが予想されます。では、なぜこの技術がこれほど注目されるのでしょうか？
以下にその理由を探ってみましょう！

## エンターテインメントとメディアの進化

Tik TokやYoutubeなどで自動音声読みおこしを使った動画を見たことがある方も多いのではないでしょうか？
すでに我々が違和感なく聞ける段階まで技術は進歩しています。また、生成AIによって台本を自動で作成し、音声読み起こしで動画作成を行うケースが徐々に増えてきています。

## AWS SUMMIT 2024会場案内

先日行われたAWS SUMMITでは、AIを活用した会場案内が行われました。
具体的には、音声認識技術と生成AI、アバター技術を組み合わせ、訪問者からの質問に対する回答を生成し、音声合成技術で案内するというシステムが導入されていました。
今後は最新の技術イベントだけなく、より私たちの身近なところで使われていくかも知れません。

https://aws.amazon.com/jp/summits/japan/

## カスタマーサポートの改善

企業のカスタマーサポートでも、AI音声技術は大いに活用されています。自動音声応答システム（IVR）は、顧客の問い合わせに迅速かつ正確に対応することができ、顧客満足度を向上させる一方で、オペレーターの負担を軽減します。

## アクセシビリティの向上

テキストを音声に変換する技術は、視覚障害者や読み書き障害のある人々にとって非常に重要です。これにより、書籍、ウェブサイト、メールなどの情報に簡単にアクセスできるようになります。特に、スマートフォンやタブレットの普及により、誰でも簡単に利用できる環境が整っています。

## マルチタスキングのサポート

現代の多忙なライフスタイルにおいて、複数のタスクを同時にこなすことが求められます。テキスト読み上げ技術を使用すれば、運転中や家事をしている間に、ニュースを聞いたり、メールを確認したりすることができます。これにより、時間を有効に活用できるようになります。

# まとめ

テキストを話してくれるAI技術は、アクセシビリティの向上、マルチタスキングのサポート、カスタマーサポートの改善、エンターテインメントとメディアの進化、そして自然な対話の実現といった多くの分野で大きな可能性を秘めています。
この技術の進化は、私たちの生活をより便利により身近なものになっていくと思います。
UbuntuにROS2 humbleをインストールする

### 概要：
Ubuntu 22.04にROS2 Humbleをインストールする手順を説明します。

1. Ubuntuの更新:
   ```
   sudo apt update && sudo apt upgrade -y
   ```
   - `apt update`: パッケージリストを最新の状態に更新します。
   - `apt upgrade`: インストール済みのパッケージを最新バージョンにアップグレードします。

2. 必要なパッケージのインストール:
   ```
   sudo apt install software-properties-common
   sudo add-apt-repository universe
   ```
   - `software-properties-common`: リポジトリの追加や管理を容易にするツールをインストールします。
   - `add-apt-repository universe`: Ubuntuの「Universe」リポジトリを追加します。

3. ROS 2リポジトリの追加:
   ```
   sudo apt update && sudo apt install curl gnupg lsb-release
   sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
   echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
   ```
   - 最初の行: `curl`（データ転送ツール）、`gnupg`（暗号化ツール）、`lsb-release`（Linuxディストリビューション情報ツール）をインストールします。
   - 2行目: ROS 2の公式GPGキーをダウンロードし、システムに追加します。ROS 2のパッケージの信頼性を確認することができます。
   - 3行目: ROS 2のパッケージリポジトリをシステムのソースリストに追加します。これにより、`apt`を使ってROS 2をインストールできるようになります。

4. ROS 2 Humbleのインストール:
   ```
   sudo apt update
   sudo apt install ros-humble-desktop
   ```
   - パッケージリストを更新した後、ROS 2 Humbleのデスクトップ版をインストールします。これには、ROS 2の主要なライブラリやツールが含まれています。

5. 環境のセットアップ:
   ```
   echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
   source ~/.bashrc
   ```
   - 1行目: ROS 2の環境設定スクリプトを、ユーザーのbashrc（ターミナル起動時に実行されるスクリプト）に追加します。
   - 2行目: 変更を即座に反映させるため、bashrcを再読み込みします。

6. 依存関係のインストール:
   ```
   sudo apt install python3-colcon-common-extensions
   ```
   - colconというビルドツールの拡張機能をインストールします。これはROS 2のパッケージをビルドする際に必要です。

7. インストールの確認:
   新しいターミナルを開いて以下のコマンドを実行し、インストールを確認します：
   ```
   ros2 run demo_nodes_cpp talker
   ```
   別のターミナルで：
   ```
   ros2 run demo_nodes_py listener
   ```
   - これらのコマンドは、ROS 2の基本的な通信機能をテストします。
   - `talker`ノードは「Hello World」メッセージを発行し、`listener`ノードはそれを受信します。
   - 正常に動作すれば、`talker`側で発行したメッセージが`listener`側で表示されます。

8. rqt_graphでノードの確認:

```
rqt_graph
```

グラフィカルインターフェースが表示され、現在のROS2システムのグラフが表示されます。talkerとlistenerが起動している様子がわかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73020/570acaad-1ebb-f1c9-4550-e5c9441d6152.png)
IBM i Services Directory : QSYS2.Active_DB_Connections 表関数

このIBM i (Db2 for i)に対するDRDA、DDM、Db2 Mirror の接続1つに対して1行を返します。
**一般的なデータベース接続方法であるJDBC, ODBC等の情報は当IBM i サービスでは返されないので注意。**

## 概要
■表関数名：QSYS2.ACTIVE_DB_CONNECTIONS
■カテゴリ：通信サービス
■サポート：IBM i 7.3 SF99703 Level 16以降 その後2回拡張
■参照URL（IBM i 7.5）：https://www.ibm.com/docs/ja/i/7.5?topic=services-active-db-connections-table-function

## 実行例

```
SELECT * FROM TABLE (QSYS2.ACTIVE_DB_CONNECTIONS('900239/DBADMIN/QPADEV000F'));
```

※上記はマニュアル記載のサンプルです。QPADEV000Fという5250端末, ユーザーID DBADMIN、ジョブ番号900239 のジョブが実行しているDDM, DRDA, Db2 Mirror の通信ジョブ毎に1行を返します。


## DDM, DRDA　ってなに？

DDMは昔からよく使われているIBM i OS同士でリモートのDb2 for i のテーブル・ビューをローカルのテーブル・ビューのように見せるためのオブジェクトです。***ローカルにCRTDDMFコマンドでタイプ\*FILE 属性DDMFのテーブルを作成すると、ローカルのプログラム等（RPG,COBOL,Java,OSS,CLP,etc.）からDDMFを指定して、リモートのDb2 for i をアクセスできます。***

・・・ですが、JavaなどODBC/JDBC等が利用できる言語ではそもそもローカル・リモートの区別は普通しないのでRPG,COBOL,CLPなど上記を使わない言語からもっぱら使われます。

DRDAは Distributed Relational Database Architecture の略で、主にDb2ファミリー間（OSは問わない異機種間接続を想定）のデータベース通信、連携技術です。

参照：https://www.ibm.com/docs/ja/informix-servers/12.10?topic=communications-overview-drda


### DDMFの作成例

サンプルの全体像です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/647ec655-25cf-70c0-2159-943f33f40b7d.png)


以下のようなコマンドで作成します。
```
CRTDDMF FILE(GOMALIB/TOKMSP75) RMTFILE(DEMOLIB/TOKMSP) RMTLOCNAME(IBMI75 *IP)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/0f6a2e76-2df4-bdaa-a83c-c7c7f3b91cd1.png)

***この例ではIBMI74システム上にリモートのIBMI75のスキーマ：DEMOLIB、テーブル：TOKMSPをアクセスできるDDMファイル：TOKMSP75が作成されます。***

### DDMジョブを開始してみる。

色々やり方はありますがここでは、IBMI74システムのACS SQLスクリプト実行画面から上記のDDMファイルをSELECT してみます。

```
SELECT * FROM GOMALIB.TOKMSP75 ;
```

実行結果は…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/2b4c1fe9-cc4b-a05b-cc26-fa8a15b9ed7c.png)
エラーになりました…T T) 
おっと忘れてしました、DDMFはSQL,QUERY/400では使えませんでした・・・(^^;

では別な方法でDDMFをアクセスしてみましょう。
単純な方法として、DFUでリモートのPFを更新モードでオープンしてみます。

以下のファイルの実体は
リモートシステム：IBMI75
ファイル　DEMOLIB/TOKMSP  です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/1b146e77-83cd-5407-22c2-7a59a458b537.png)


下記の例のようにリモートのファイルを更新モードで開けばDDMセッションがアクティブになるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/2654130c-640f-2c8a-c92a-b073f8b521cc.png)

ここで、実行している5250画面のジョブ番号/ユーザー名/端末名を調べて、ACS SQL実行から実行します。

実行例です。
```
SELECT * FROM TABLE (QSYS2.ACTIVE_DB_CONNECTIONS('633699/GOMA/QPADEV0007'));
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/78447bf9-a2a9-d35e-db11-b1f74ac2aad4.png)

この後のカラムには、クライアントIPアドレス、ホストIPアドレス、リモートのIBM i OSバージョンなどが返されています。


## QA

Q1.
タイプの FILE には アスタリスク (*) が付くけど、属性の DDMF には付かなかったりするでしょうか？

A.
下記の例のようにDDMFは*FILEタイプオブジェクトのなかの１つの属性となります。*FILEタイプオブジェクトの別な属性の種類としては、PF-DATA(テーブル、物理ファイル）、SAVF（保管ファイル）、などがあります。
属性には\*は付けないのが慣例的な表現法です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/72aff3d6-c9d3-235b-ae8d-7de2f6e4852d.png)
AWS Certified Cloud Practitioner CLF-C02 に合格したよ

2024年6月に AWS Certified Cloud Practitioner CLF-C02 認定試験に合格することができました。
合格に至った過程などについて書いてみます。

## 受験経緯
2024年3月、AWSがあるキャンペーンを展開していました。
それは4月30日までに受験して不合格だった場合、6月末まで無料でもう1回受験できるというものでした。
「6月までには合格できるんじゃない？とりあえず受けてみるか！」
そう思ったのが受験することにしたきっかけです。

## 試験勉強開始時の AWS 経験
2014年10月から12月まで携わった案件で初めて AWS に触れました。
そのときはおもに Cloud Formation のコード作成を担当しました。
業務で AWS に触れたのはそれが最後で、2015年後半以降に担当した案件で Microsoft Azure にはじめて触れ、仮想マシン構築などを担当しました。
クラウドについての知識はなんとなく溜まっていきました。

## 受験1回目（2024年4月）
前述のとおり、6月末までに無料で受験するには4月中に1度受験する必要があったのでひとまず受験しました。試験対策はとくにせず、予定どおり不合格でした。
試験中は「これはいけたのでは？」とも思いましたが…。

## 試験対策
AWS の認定試験があることは以前から知っていて、いつか受験しようと思っていたのであらかじめ Udemy の講座をいくつか購入していました。
「基本4択問題だし、とりあえず問題と答えの組み合わせを暗記したらよいのでは？」
と思い、模擬試験の講座に着手しました。
が、そもそも何のサービスだか分からないものについて暗記するのは難しく、まずはサービス名とサービス内容を理解することにしました。
たとえば DynamoDB は DB 関係のサービスだと分かりますが、Aurora やら Lambda などはどういうサービスなのか名前から察することができませんでした。
そこで各サービスについて簡単に説明する YouTube 動画をひと通り視聴しました。
その後、Udemy の模擬試験 5回分を3周ちょっとしました。

### 視聴した YouTube 動画
AWS資格 対策講座
https://www.youtube.com/@AWS_course
クラウドプラクティショナーの動画をひと通り視聴しました。

### 受講した Udemy 講座
【CLF-C02版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（6回分390問）
https://www.udemy.com/course/aws-4260/
1回目の正答率は40%台でしたが、2回目には80%から90%台になりました。
全問正解する必要はないのですが、この模擬試験6回すべて満点を目指して問題と正答の暗記に努めました。

## 受験2回目（2024年6月）
受験1回目よりも「これは合格しちゃったなー」という実感を得られました。

## 合格までにかかった期間
4月の受験は、無料で再受験する権利を得るためのものであって対策は立てていませんでした。
YouTube で各サービスについて学習したのが合格の4日前だったので5日目で合格したといってよいと思います。
### 1日目
YouTube でひと通りのサービスについて視聴。冒頭の定型部分はスキップして1.5倍速で視聴。
### 2日目から4日目
Udemy の模擬試験の問題と答えを暗記する。1回目にあまり時間をかけない。1回目の正答率は重要ではなく、問題と正答の組み合わせを暗記して2回目以降の正答率を高めていくことが重要。

### 5日目 試験当日
Udemy の iOS 版アプリで復習しながら試験会場へ。

## まとめやら感想やら
今回、AWSのキャンペーンがあったので受験することにしましたが、それがなかったら受験していなかったと思います。
まず受験日を決めてしまうことが重要ですね。
Udemy の模擬試験は本番試験より難しい印象です。模擬試験では選択肢4つのうち2つ除外できた後で残りの2つで迷うことがあったのに対して本番で迷うことはほとんどありませんでした。
また、「セキュリティのパースペクティブ」や「ビジネスのパースペクティブ」などのようななんとかパースペクティブの整理ができていなくて模擬試験での正答率が低く、図にしてしっかり理解する必要があると思っていましたが本番試験ではそれほど細かいことは訊かれませんでした。
AWS の認定の中ではいちばんお求めやすいものではあるものの、自力で試験対策をするのは難しいと思います。先達たちが模擬試験を用意してくれているのでそれを利用して効率よく合格するのはありだと思います。
複数ブランチを一括コミットしたいときの自分用シェル

### 複数ブランチを一括コミットしたいときの自分用シェル

````
#!/bin/bash

# 二次元配列: プロジェクト名と対応する番号
projects=(
    "プロジェクトA 3"
    "プロジェクトB 6"
    "プロジェクトC 11"
)

# プロジェクトごとに処理
for project in "${projects[@]}"; do
    # プロジェクト名と番号を分割
    IFS=' ' read -r -a project_info <<< "$project"
    project_name="${project_info[0]}"
    project_number="${project_info[1]}"

    # ディレクトリに移動
    cd "/c/src/$project_name" || exit

    # ブランチ名とコミットメッセージを作成
    branch_name="feature_${project_number}_hogehoge"
    commit_message="テスト #${project_number}"

    # Gitコマンドを実行
    git checkout -b "$branch_name"
    git add .
    git commit -m "$commit_message"
    git push origin "$branch_name"
done

````
npm、npx、yarnを簡潔に理解

# npm、npx、yarnの違い :beginner:
JavaScriptのパッケージ管理ツールとして、npm、npx、およびyarnは広く使用されています。それぞれのツールの違いを理解して、適切に使い分けることで、開発作業を効率化できます。この記事では、npm、npx、yarnの違いを解説し、どのような場面で使い分けるべきかを紹介します。


![napkin-selection (21).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690843/97c7bc1f-e412-807f-2824-99af23126c61.png)


## npm とは？
#### 概要
npm（Node Package Manager）は、Node.jsのためのパッケージ管理ツールです。これにより、JavaScriptパッケージのインストール、アップデート、アンインストールを簡単に行うことができます。

#### 主なコマンド
npm install : パッケージをインストールします。
npm install [パッケージ名] : 特定のパッケージをプロジェクトにインストールします。
npm install -g [パッケージ名] : パッケージをグローバルにインストールします。
npm uninstall [パッケージ名] : パッケージをアンインストールします。
npm update : パッケージをアップデートします。
npm init : 新しいNode.jsプロジェクトを初期化します。
ユースケース
プロジェクトの依存関係を管理する。
パッケージをインストールして使用する。
プロジェクトの初期設定を行う。
## npx とは？
#### 概要
npx（Node Package Execute）は、npmに同梱されているツールで、パッケージをインストールせずに一時的に実行するためのツールです。これにより、ローカルまたはグローバルにパッケージをインストールすることなく、コマンドを実行できます。

#### 主なコマンド
npx [コマンド] : 指定したコマンドを実行します。
例: npx create-react-app my-app : create-react-appを使用して新しいReactアプリを作成します。
npx [パッケージ名]@[バージョン] : 特定のバージョンのパッケージを一時的に使用してコマンドを実行します。
例: npx [email protected] create-react-app my-app : 旧バージョンのcreate-react-appを使用してアプリを作成します。
ユースケース
一度きりのコマンド実行のためにパッケージをインストールする必要がない場合。
特定のバージョンのパッケージを一時的に使用したい場合。
グローバルインストールを避けたい場合。
## yarn とは？
#### 概要
yarnは、Facebookが開発したJavaScriptのパッケージ管理ツールで、npmと同様の機能を持ちつつ、いくつかの利点を提供します。高速なインストールと安定性の向上を目指して設計されています。

#### 主なコマンド
yarn install : パッケージをインストールします。
yarn add [パッケージ名] : 特定のパッケージをプロジェクトにインストールします。
yarn global add [パッケージ名] : パッケージをグローバルにインストールします。
yarn remove [パッケージ名] : パッケージをアンインストールします。
yarn upgrade : パッケージをアップデートします。
yarn init : 新しいNode.jsプロジェクトを初期化します。
ユースケース
高速な依存関係のインストールが必要な場合。
安定したバージョンの依存関係を確保したい場合。
npmと互換性があるため、既存のnpmプロジェクトでも使用可能。
npm、npx、yarnの使い分け
npm を使うべき場合
プロジェクトで継続的に使用するパッケージを管理する際。
プロジェクトの依存関係を明示的に管理したい場合。
npx を使うべき場合
一度だけ使用するパッケージを実行したい場合。
グローバルにインストールする必要がない場合。
特定のバージョンのパッケージを試したい場合。
yarn を使うべき場合
高速なパッケージインストールが必要な場合。
より安定した依存関係管理を求める場合。
既存のnpmプロジェクトでの互換性を保ちつつ、yarnの利点を活かしたい場合。
## まとめ
npm、npx、およびyarnは、それぞれ異なる用途と利点を持つツールです。npmはパッケージの管理とプロジェクトの依存関係の管理に適しており、npxは一時的なパッケージ実行や特定バージョンの使用に便利です。yarnは高速かつ安定したパッケージ管理を提供します。これらのツールを適切に使い分けることで、開発作業をより効率的に進めることができます。
データサイエンス・コミュニケーションの実践

さて、前回の記事　https://qiita.com/Econostasis/items/43217fb579cdecf27920
でデータサイエンス・コミュニケーションとは何かを考えました。次は具体的にどうやってコミュニケーションをとっていけばいいのかを考えてみます。
これは私自身が普段心に留めながら上長（やクライアント）とコミュニケーションをとっている内容です。

## その1: 相手と自分の知識のバランスを意識
これは結構基本的で、かつ重要なことです。
先に書いた通りプロジェクトによっては説明して決裁を仰ぐメンバー側に情報の面での優位性が生まれ、リーダーは細かい内容までわかっていない状況は多いです。そこで細々と独自の用語を並べて説明してもリーダーはよく理解できずイライラ、みたいなことが頻発します。
説明する側の責任として、相手だけが理解していないこと、両方が理解していること、自分だけが理解していないことをできる限り考慮して話すことが重要です。
技術が絡む報告だとこういった細かい知識が膨大にあるので、それだけ摩擦も発生します。まずは時間をかけて知識の整理を行うのが良いです。

## その2: MTG後の相手の姿をイメージする
これは話す内容を取捨選択しているときに効くのですが、何を伝えて何を伝えないのかは結構迷いどころです。
そんな時には、MTG後の相手にはどんな姿になってほしいか？をイメージします。タスクの概要を知ってもらいGOサインを出してもらいたいのか？起きている小さな問題点を報告して改善点が浮かぶようになっていてほしいのか？この後のお客様との打ち合わせで発表するため、経緯や結果を含めたストーリーを知ってもらいたいのか？

MTG自体の目的に応じて伝える内容は変わってきます。そして何より大事なのが
**自分が逆の立場だったら、何をわかっていれば目的が達成されるか？というイメージ**です。
自分を俯瞰で見つめ、白紙の状態から目的達成のための知識をリストアップし、大から小に向かって説明するという動作こそ、取捨選択そのものになります。

大事なのはイメージです。

## その3: 話し始めはタスクの「目的」から
これもよくあったのですが、リーダーは結構忙しい立場の人が多く、いろいろなプロジェクトを並行して束ねていることも珍しくないです。加えてマネジメント業務なども兼任しており、とにかく時間がないものという認識です。

そんな中でのレビューでは、「そもそも何やってたんだっけ？」が頻発するので、まずは今やっている作業の目的に立ち返って報告するのが親切です。

上流に行き過ぎると時間がかかりすぎるので、タスクの結果から何を見たいのか、くらいから話し始めるとお互いの認識がそろった状態で始められることが多いです。

## その4: コードを画面共有しながらポイント解説
これは状況によりますが、今までの経験からクエリやコードを画面共有しつつ、前回調査との差分はどこか、（SQLなら）各一時テーブルの役割、単体テストの結果一覧などを見せて大まかな作業スキームを**時間内に** 説明するとすごく喜ばれます。（時間内に終わらせる必要があるので、クエリをいちいち全部は説明しません。まあ集計条件に直接絡んできそうなカラムのつくりや、レコードの絞り方などは口頭で触れるくらいです。）
自分の周りの環境だと、クエリやコードは投げて「あと見といて」な状態が結構あるようで、自分はなるべくそれをしないように心がけています。
口頭でイメージだけ伝えておけば、細かいところはあとで見てもらうことができるので結構効率的だったりします。
これはデータサイエンス分野にジョインして初めての経験でした。自分でクエリを説明する機会を作ると、構造やポイントを俯瞰で見ることになるので後々のコーディングにも役立つトレーニングになります。

## まとめ
思いつくままにざっと書きましたが、これ以外にもまだまだあります。
どれも当たり前のことではありますが、いざという場面で結構抜けてたりします。
コミュニケーションをとる際は改めて思い出しておくとよいのではないでしょうか！
タイポとは？ちょっとためになるかもしれないお話

## はじめに
分からないことをGPTに質問していく中、もらった回答の意味が分からなく、その回答の意味を更にかみ砕いて説明してほしい。といたちごっこのような状態がしばしばおこっているわーちゃんです。
今回はそんなもらった回答の中で「タイポ」という言葉がはじめみたとき、全くわからなかったので解説したいと思います


## タイポって何？
英語表記で**typo:誤字脱字**
具体的には、文字の入力ミスやキーボードの打ち間違いによって生じる文字の誤りを指します
例えば、単語のスペルが間違っていたり、文字が抜けていたりする状態がタイポです

## 由来
- 英語の「typographical error」からきています
- これは印刷の世界で使われる用語となり、活字を組む作業での誤りを指す言葉です
- 活字組版の時代には、手作業で文字を配置する作業があり、間違いが生じやすかったため、これが広まったとされています

![タイピング.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777936/e3a28e06-4e8b-1f4f-002a-2c3efc7ae6ad.jpeg)


## 似たような言葉
プログラミングの文脈において、他にも**スペルミス：spelling mistake**や**入力ミス：input error**といった言葉が使われます
しかし、「タイポ」の方が比較的一般的な用語として広まっているそうです
また、「誤字」という言葉も同様の意味で使われますが、語感や使用頻度に違いがあります

## さいごに
今回の**タイポ**のお話をきき、ためになるかは個々人次第です。現場を知らないので何とも言えないのですが、「タイポ」という言葉は実際に使うのかは謎です:thinking:
三項演算子は入れ子にできる

タイトルの通り。
知らなかったので記事にまとめます。

## 三項演算子とは
その名の通り三項、つまり3つの値を持ってif文の省略形・代替手段として使用することができるものです。


以下のような関数があったとします。
```js
/**
 * 引数が10より小さい場合はtrue、10以上の場合はfalseを返す
 * @param {number} num
 * @returns {boolean}
 */
const isLowerThan10 = (num) => {
  if (num < 10) {
    return true;
  } else {
    return false;
  }
};

console.log(isLowerThan10(5)); // true
console.log(isLowerThan10(100)); // false
```

if文の例としてはわかりやすいですが、冗長な書き方にはなってしまいます。
これをよりシンプルに書くために使用されるのが三項演算子です。

**条件式**、**trueの場合の処理**、**falseの場合の処理**の3つを`?`と`:`で連結させて記述します。

```
{条件式} ? {trueの場合の処理} : {falseの場合の処理}
```

先ほどのif文を三項演算子に置き換えると、以下のようになります。

```js
num < 10 ? true : false
```

さらに関数に当てはめると、以下のようになります。
```js
/**
 * 引数が10より小さい場合はtrue、10以上の場合はfalseを返す
 * @param {number} num
 * @returns {boolean}
 */
const isLowerThan10 = (num) => {
  const result = num < 10 ? true : false;
  return result;
};

console.log(isLowerThan10(5)); // true
console.log(isLowerThan10(100)); // false
```

:::note info
三項演算子の説明のために敢えてこのような書き方をしていますが、本来は以下の書き方で十分です。
:::

```js
const result = num < 10;
```

## 条件演算子の入れ子構造について
if文の連鎖的な書き方でよく見るのは、以下の2種類かと思います。

```js
// 入れ子になっているパターン
if (条件A) {
  if (条件B) {
    ...
  }
}

// else ifで連結されるパターン
if (条件A) {
  ...
} else if (条件B) {
  ...
} else if (条件C) {
  ...
}
```

これらは三項演算子で書き換えることが可能です。

### 入れ子
```js
const result = 条件A ? 条件B ? B : C : A;
```

括弧で区切るとわかりやすいかと思います。

```js
const result = 条件A ? (条件B ? B : C) : A;

// 以下のif文と同義
if (条件A) {
  if (条件B) {
    return B;
  } else {
    return C;
  }
} else {
  return A
}
```

### 連結
```js
const result = 条件A ? A : 条件B ? B : C;
```

こちらも括弧で区切るとわかりやすいです。
```js
const result = (条件A ? A) : (条件B ? B) : C;

// 以下のif文と同義
if (条件A) {
  return A;
} else if (条件B) {
  return B;
} else {
  return C;
}
```

## どういう時に使うか
個人的には可読性が大きく下がるため、乱用することはあまりしたくありません。

一方で記述量を減らすことができるため、関数コンポーネントなど、
最初に大きく整備して、長く運用していくようなファイルでは活用できるのではないでしょうか。

また、TypeScrpの型定義ファイルでは多く活用されているようです。

```ts
// 2種類の型をマージし、新しい型を作成する
type Merge<T, K> = {
  [U in keyof T | keyof K]: U extends keyof K
  ? K[U]
  : U extends keyof T
  ? T[U]
  : never;
};

type Hoge = {
  name: string;
  age: number;
};

type Fuga = {
  age: number;
  birth: number; 
};

type Result = Merge<Hoge, Fuga> // {name: string, age: number, birth: number};
```
三項演算子で記述している部分を無理やりif文にすると以下のようになります。
```ts
if (U extends keyof K) {
  return K[U];
} else if (U extends keyof T) {
  return T[U];
} else {
  return never;
}
```

## 参考文献
[条件 (三項) 演算子 - JavaScript - MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Conditional_operator)
[【JavaScript入門】条件(三項)演算子の使い方と活用例まとめ！](https://www.sejuku.net/blog/23627)
セレクトボックス

```tsx
import React, { useState } from 'react';
import { Typography, Select, MenuItem, FormControl, InputLabel, Box } from '@mui/material';

const SelectBoxWithTitle: React.FC = () => {
  const [age, setAge] = useState<string>('');

  const handleChange = (event: any) => {
    setAge(event.target.value as string);
  };

  return (
      <Box sx={{ display: 'flex'}}>
      <Typography 
        variant="h6" 
        component="div" 
        sx={{ display: 'flex', alignItems: 'center',minWidth: 120}}
      >
        Select Age {age ? ' ' : '*'}
        </Typography>
        <FormControl variant="outlined" sx={{ marginLeft: '16px', width: 200 }}>
          <InputLabel id="select-age-label">Age</InputLabel>
          <Select
            labelId="select-age-label"
            id="select-age"
            value={age}
            onChange={handleChange}
            label="Age"
          >
            <MenuItem value="">
              <em>None</em>
            </MenuItem>
            <MenuItem value={10}>Ten</MenuItem>
            <MenuItem value={20}>Twenty</MenuItem>
            <MenuItem value={30}>Thirty</MenuItem>
          </Select>
        </FormControl>
        </Box>

  );
}

export default SelectBoxWithTitle;

```
過去問「秒後には問題文」???を調べた。「は」の使い分けです。リズム感?


申し訳ありません。私は問題文を理解していません。

# 例1.
2024　東京大学　前期MathJax理科【３】(ⅱ)　
＞その1秒後にはPは...
　　　↓  ???
＞その1秒後にPは...
https://mathexamtest.web.fc2.com/2024/202410261/2024102610100mj.html#top-0103

# 例2.
＞分経過
2022 大学入学共通テスト 本試験 数学II・IIB
自転車君の問題文に"分後"。ありません。
https://mathexamtest.web.fc2.com/2022/202210000/2022100000200mj.html#top-0208


# 例3.(別件)欄には
2024　公立千歳科学技術大学　前期MathJax
https://mathexamtest.web.fc2.com/2024/202411025/2024110250100mj.html
＞以下の問いに答えなさい．解答欄には答えのみ書きなさい．
　　　　　↓OKです。たしかに「は」がないと調子がつきません。
＞以下の問いに答えなさい．解答欄に答えのみ書きなさい．

# deeplで

https://www.deepl.com/ja/translator#ja/en/以下の問いに答えなさい．解答欄には答えのみ書きなさい．
https://www.deepl.com/ja/translator#ja/en/以下の問いに答えなさい．解答欄に答えのみ書きなさい．

Answer the following questions. Write only the answer in the answer column.
Answer the following questions. Write only the answer in the answer column.


# ChatGPTで

```
以下の問いに答えなさい．解答欄には答えのみ書きなさい．
上の文と下の文の違いを教えて下さい。
以下の問いに答えなさい．解答欄に答えのみ書きなさい．
```
```
詳しく
```
(抜粋)...
まとめ
上の文は、「解答欄には」という表現で、解答欄以外の場所に書かないことを強く意識させる指示。
下の文は、「解答欄に」という表現で、解答欄に書くことを指示するが、特に解答欄以外に書かないことを強調するニュアンスはない。
この違いにより、文の指示の強さや焦点の当て方が変わってきます。

# 「”秒後には”問題文」の過去問

・サイト内検索　＜　大学入試数学問題集成 様

https://cse.google.com/cse?cx=a8908fbc24340ebc5&q=%E2%80%9D%E7%A7%92%E5%BE%8C%E3%81%AB%E3%81%AF%E2%80%9D&oq=%E2%80%9D%E7%A7%92%E5%BE%8C%E3%81%AB%E3%81%AF%E2%80%9D&gs_l=partner-web.12...802195.802195.0.804119.1.1.0.0.0.0.188.188.0j1.1.0.csems%2Cnrl%3D10...0....1.34.partner-web..1.0.0.8_dwaauHLcM
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（53/100）

【53日目】
トピック 6：SAPS/4HANAの需要管理（4/5）

≪問題53≫
対応する最終製品の受注を受領する前に、半製品の内製を開始しようとしています。半製品に対する計画独立所要量の消費がサポートされるのは、どの計画方針ですか。
□最終組立ありの計画（40）
□受注生産（20）
□組立レベルでの計画（70）
□ロットサイズによる生産（30）

≪解答≫
□最終組立ありの計画（40）
□受注生産（20）
■組立レベルでの計画（70）
□ロットサイズによる生産（30）

≪解説≫
◆組立品目レベルでの計画（計画方針70）は、多様な最終製品の所要量予測を指定するよりも、特定の組立品目（半製品）の所要量予測を指定するほうが容易である場合に役立ちます。
◆この計画方針では、組立品目の計画は個別に考慮されます。計画独立所要量は組立品目レベルで入力し、それによって組立品目の生産がトリガーされます。
◆最終製品の受注を受け入れた場合、最終製品のBOMが展開され、最終製品の計画手配または製造指図の結果として、組立品目の従属所要量や入出庫予定も登録されます。これらにより、組立品目の計画独立所要量が消費されます。
見落としがち、小賢しいsaveとsave!

## はじめに
学習を進めていく中、頻繁に登場するようになってきた`save`と`save!`。この`!`の有り無しだけで意味がだいぶ変わってくるなんて…。
アウトプットとしてそれぞれの違いと、簡単な例を挙げてみます。

## saveメソッド
- Active Record モデルのインスタンスをデータベースに保存します
- 保存が成功した場合、true を返しますが、保存に失敗した場合は false を返します
- 保存に失敗した場合、エラーが発生することなく単に false を返すだけです

```
# Example with save
user = User.new(name: "John")
if user.save
  puts "User saved successfully!"
else
  puts "Failed to save user."
end
```


## save!メソッド
- save メソッドと同様にインスタンスをデータベースに保存しますが、保存に失敗した場合には例外 ActiveRecord::RecordInvalid を発生させます
- つまり、save! メソッドは保存が成功するか、もしくは例外が発生するまで実行がブロックされます
- バリデーションに失敗する可能性がある場合や、データベース障害などの非常に稀なケースに対して、save!を使用することが推奨されます
```
# Example with save! and exception handling
# 通常の条件分岐でsave!を使用する場合例外処理を行う begin...rescue ブロックで囲む必要がある
begin
  if user.save!
    puts "User saved successfully!"
  else
    puts "Failed to save user."
  end
rescue ActiveRecord::RecordInvalid => e
  puts "Failed to save user: #{e.message}"
end
```
```
# Example with save!
begin
  user.save!
  puts "User saved successfully!"
rescue ActiveRecord::RecordInvalid => e
  puts "Failed to save user: #{e.message}"
end
```

## 似たような仕組み：create メソッド
- save メソッドと同様にインスタンスを保存しますが、新しいレコードを作成し保存します
- 保存に失敗した場合は、false を返します
```
# Example with create
user = User.create(name: "Alice")
if user.persisted?
  puts "User created successfully!"
else
  puts "Failed to create user."
end
```

## トランザクションとの組み合わせ技
※トランザクション内で複数の save や save! を行い、それらが全て成功した場合にのみコミット（確定）、途中でどれか一つでも失敗した場合には全てをロールバック（取り消し）する、という使い方
### save メソッドとトランザクションの例
```
ActiveRecord::Base.transaction do
  user = User.new(name: "Alice")
  if user.save
    address = Address.new(street: "123 Main St", city: "Anytown")
    if address.save
      puts "User and address saved successfully!"
    else
      raise ActiveRecord::Rollback, "Failed to save address."
    end
  else
    raise ActiveRecord::Rollback, "Failed to save user."
  end
end
```
- ユーザーが保存されなかった場合には、そのユーザーに関連付けられた他のデータも同時にロールバックされるため、データベース内で不整合が生じることを防ぐことができる
- このコードはアリスという名前で新たなユーザーを作っている。もしアリスがsaveされたら新しいアドレスを登録できる。そして新しいアドレスも無事登録出来たら成功。そうでなかったらアドレス失敗。前段階のユーザーの登録がちゃんと登録できなかったらユーザー登録失敗
- まとめると、トランザクション開始＞ユーザー保存＞アドレス保存＞アドレス保存失敗＞ユーザー保存失敗

### save! メソッドとトランザクションの例
```
begin
  ActiveRecord::Base.transaction do
    user = User.new(name: "Bob")
    user.save!

    address = Address.new(street: "456 Elm St", city: "Othertown")
    address.save!

    puts "User and address saved successfully!"
  end
rescue ActiveRecord::RecordInvalid => e
  puts "Failed to save user or address: #{e.message}"
end
```
- ボブで登録してsaveする。アドレスを登録してsaveする。そしてユーザーとアドレス登録成功の文字。どちらかの登録でエラーが起きたらユーザーまたはアドレスの登録失敗という文字が発生
- つまり、ユーザー保存＞アドレス保存＞成功時メッセージ＞保存失敗時の処理


## さいごに
`save`と`save!`のちがいを紹介しました。銀行なんかの引き落とし処理や重要なパスワードの処理など、厳しい基準を設けたいならトランザクションやsave!を使用したほうが安全なのかなと感じました。
少しでも参考になれば幸いです。
Railsのフォロー機能実装中にbelongs_toの書き方を間違えてActiveRecord::AssociationTypeMismatchエラーが出た話

## 読んで欲しい人

- belongs_toの書き方をちゃんとわかってない人
- ActiveRecord::AssociationTypeMismatchエラー出た人
- 過去の俺

## 動作環境

- ruby 3.3.0
- Rails 7.1.3.3

## やってたこと：悪い例

フォロー機能を実装してました。

- フォローする側：follower
- フォローされる側：followed

```user.rb
class User < ApplicationRecord
  has_many :active_relationships, class_name: 'Relationship', foreign_key: 'follower_id', dependent: :destroy, inverse_of: 'follower'
end
```
※ フォローされる側の実装はしていない

```relationship.rb

# このファイルの記述が間違ってた。

class Relationship < ApplicationRecord
  belongs_to :follower_id, class_name: 'User'
  belongs_to :followed_id, class_name: 'User'
end
```

```2024070560413_create_relationships.rb
# Relationshipsテーブルのマイグレーションファイル
class CreateRelationships < ActiveRecord::Migration[7.1]
  def change
    create_table :relationships do |t|
      t.integer :follower_id, null: false
      t.integer :followed_id, null: false

      t.timestamps
      t.index %i[follower_id followed_id], unique: true
    end
  end
end
```

#### ActiveRecord::AssociationTypeMismatchエラーの原因

```relationship.rb
class Relationship < ApplicationRecord
  belongs_to :follower_id, class_name: 'User'
  belongs_to :followed_id, class_name: 'User'
end
```
- `belongs_to :follower_id`ではなく`belongs_to :follower`
- `belongs_to :followed_id`ではなく`belongs_to :followed`

です。

マイグレーションのカラム名を指定してました。

## belongs_toの使用方法について

`belongs_to(関連モデル名, scope=nil, オプション={})`

- belongs_toの第一引数は、関連するモデル名であり、idではない

## 感想・学び

- そのコードの意味や正しい使用方法を知らないとロクなことがない
- コードを記述する以上、人に説明できるコードを書くべき

以上です。