OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerコンテナ内のプロセスをcronで実行できなかった

# はじめに
個人開発でDockerコンテナ内にて動いているWebアプリのSSL証明書(Let's Encrypt)をcronによって自動で更新しようとした際に上手く動作させることができませんでした。
結論から言えばただのパスの通し忘れだったのですが、Dockerコンテナの性質であったり、docker composeコマンドを使用しているからだったりと多くの勘違いの末に膨大な時間をかけてようやく解決できたので、備忘録として残しておきたいと思いました。

# 発生した問題
cronジョブ内で`docker-compose`コマンドを使用しようとした際に、コマンドが見つからないというエラーが発生し、SSL証明書の自動更新が実行できませんでした。
```sh
/bin/sh: 1: docker-compose: not found
```

# 原因
冷静に考えたら見れば一発なのですが、この問題の原因は、cronが実行される環境のデフォルトのPATHに`docker-compose`が含まれていなかったためでした。

というわけで、crontabに以下を追記したところ、無事SSL証明書の自動更新に成功しました。
```sh
PATH=/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
```
ちなみにですが、docker-composeはDocker Compose V1のコマンドで既に非推奨です。Docker Compose V2を素直に使いましょう（戒め）。

# 反省
- エラーログをしっかりと確認しよう！
- プロセス実行環境のPATHを常に意識しよう！
ABC345備忘録【A~C】

## はじめに
[ABC345](https://atcoder.jp/contests/abc345)です！3完でした :sob:

## A - Leftrightarrow
### 問題
https://atcoder.jp/contests/abc345/tasks/abc345_a

### 考えたこと
前と後ろにのみ"<"と">"があって、"="が１つ以上あれば"Yes"、それ以外は"No"です。

### ACコード
```a.py
s = input()

if (
    s[0] == "<"
    and s[-1] == ">"
    and s.count("<") == 1
    and s.count(">") == 1
    and s.count("=") > 0
):
    print("Yes")
else:
    print("No")
```

一行で書けそうだったので挑戦してみました。中身は同じです。
```a_oneline.py
print("YNeos"[not ((s := input())[0] == "<" and s[-1] == ">" and s.count("<") == 1 and s.count(">") == 1 and s.count("=") > 0) :: 2])
```

## B - Integer Division Returns
### 問題
https://atcoder.jp/contests/abc345/tasks/abc345_b

### 考えたこと
decimalを使いました。

### ACコード
```b.py
from math import ceil
from decimal import Decimal

x = int(input())
print(ceil(Decimal(x) / Decimal(10)))
```

## C - One Time Swap
### 問題
https://atcoder.jp/contests/abc345/tasks/abc345_c

### 考えたこと
重複する文字がない場合、注目している文字以外を数え上げます。（図１）

![counting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631672/eb3268ba-12a7-4e6b-d1e5-b57690ce03df.png)

重複する文字がある場合、単純に重複する文字を数え上げないという方針で行うと、初期状態の文字列を数え忘れるので注意が必要です。

![counting_dup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631672/68e4deaf-4e95-e8ea-3152-90f0111f455a.png)

### ACコード
```c.py
from collections import defaultdict

s = input()
n = len(s)
d = defaultdict(int)

ans = 0
for i in range(n):
    d[s[i]] += 1
    if d[s[i]] > 1:
        ans = 1  # ここで重複したときの数え上げ忘れ分を調整

for i in range(n):
    d[s[i]] -= 1
    ans += (n - i - 1) - d[s[i]]

print(ans)
```

## 感想
精度が求められるときいつもdecimalを使って解いているような・・・pypyのdecimalは遅いらしくそろそろこの辺りを勉強したい（しない）
駆け出しエンジニアがプルリクで意識すること

# 初めに

こんにちは！taisei_codeです。
GitHubを使用したチーム開発で私が初めてプルリクエストを提出して、レビュワーからFB（フィードバック）をいただいてから意識していることを書いていきます。

# FBと意識すること

### 作業単位でコミットする
1つのissueを対応できたら、コミットしていたので、issueを細分化して小さな作業単位でコミットするように改善しました。具体的には、issueのゴールが「RSpecを導入してModelスペックがバリデーションを通ることを確認する」であれば、以下のように作業を小さくしてコミットします。

① インストールするGemを追加
② 自動生成されるファイルを編集
③ テストコードを書く

### PRのタイトルを作業内容に変更する

変更前は、技術的な問題で解決したいことをPRのタイトルにしていました。作業内容というのは、関連するissueで解決したい目的のこと。

### 詳細項目はレビュワーへの共有事項をメインに使う

私は詳細項目に質問フォーマットを共有していてご指摘を受けました。詳細項目には、プルリクエストの作成者が変更の内容を詳細に共有することに使われるので、技術的に質問があるときはSlackでやり取りするようにします。

# 終わりに

レビュワーからいただいたFBは直ぐに改善できる内容です。最初はプルリクエストに慣れませんが、1つずつ整理しながら作業していくことが大切だと感じました。
Djangoで作成したプロジェクトをGitHubに公開する前の諸々

備忘録として

wsl Ubuntu-22.04使用

***
①
```terminal
pip install python-dotenv
```

②
```setting.py
#Pathの下に
from dotenv import load_dotenv
import os
load_dotenv()
```
<br/>

③
.envファイル作成

<br/>

④
settings.pyの"SECRET_KEY"をコピー
↓
.envに貼り付け

```.env
SECRET_KEY = #貼り付け#
DEBUG=false(デプロイ時)
DATABASE_URL=sqlite:///db.sqlite3
# '' は不要
```
⑤
```settings.py
SECRET_KEY = os.environ.get('SECRET_KEY')
```
⑥
```terminal
pip freeze > requirements.txt
```
⑦
.gitignoreファイル作成
（ 参考：https://qiita.com/anqooqie/items/110957797b3d5280c44f ）
https://www.toptal.com/developers/gitignore
←こんなのあるんだ

⑧
```.gitignore
#example
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
instance/
.webassets-cache
.scrapy
docs/_build/
target/
.ipynb_checkpoints
venv/
ENV/
.spyderproject
.spyproject
.idea/
*.iml
.vscode/
node_modules/
.env
.DS_Store
Thumbs.db
```

⑨
よしなに
***
参考動画
https://www.youtube.com/watch?v=7tRLkZO6D3Y
https://www.youtube.com/watch?v=fVy9eJzloj8
PowerApps Sharepoint gallery checkboxの設定方法

Sharepointの複数選択項目は、checboxで表示する時があります。
設定方法を説明します。

# 設定イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/e2f570bd-382b-63ef-99ae-9707afd29a59.png)
						
						
				
							
							
					Checkbox		
						OnCheck	Collect(colCheckedRecords,ThisItem)
						OnUnCheck	Remove(colCheckedRecords,ThisItem)
						Default	If(Form.Mode<>1,If(CountRows(Filter(Combox.SelectItems,Value=ThisItem.Value))=0,false,true),false)
						Text	ThisItem.Value
							
					Gallery		
						Items	Choices([@リスト名].item名)
							
					Combox		
						Defalut	Parent.Defalut
						Items	Choices([@リスト名].item名)
							
					DataCard		
						Update	colCheckedRecords
Pyenvとvenvを使ってPython環境を使い分ける方法

PyenvとvenvによるPythonの開発環境管理方法を使うと、バージョンごとに仮想環境構築など多彩な環境構築ができるようになります。

## Pyenv:Pythonバージョン管理ツール
PyenvとはPythonのバージョン管理ができるコマンドラインツールです。
Pythonは別のバージョンを複数同時にインストールしておくことができます。複数インストールされているバージョンをひと目で確認したり、インストール・アンインストールやバージョンの切り替えが簡単にできるコマンドになっています。

### Pyenvのインストール
Pyenvのインストールは、MacであればHomebrewからが簡単。
```bash
$ brew update
＄ brew install pyenv

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
$ echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
$ echo 'eval "$(pyenv init -)"' >> ~/.zshrc
```
HomebrewでPyenvのインストール後にシェルにパスを通します。
シェルがBashの場合は``~/.Zshrc``の部分を`~/.bashrc`へ置き換えてください

### インストール済みPythonのバージョンを調べる
```bash
$ pyenv versions
  system
* 3.10.13 (set by /Users/ユーザー名/.pyenv/version)
```
現在選択されているバージョンに＊がつきます。

### インストール可能なバージョンを調べる
```bash
$ pyenv install -list
```
表示された結果内のバージョン番号のみ表示しているものがPython本体です。
python本体のほかanacondaなどもインストール可能です。

### Pythonインストール
```bash
$ pyenv install 3.X.X
```

### 各バージョンの切り替え
```bash
$ pyenv global 3.X.X     　# 3.X.Xへ切り替え

$ pyenv global system　　　　　　　　　# Macに元から入っているPythonへ切り替え
```
globalとはすべてのディレクトリで使用するバージョンを指定するコマンドです。
上記の例では、「すべてのディレクトリで使用するバージョンを3.X.Xにしなさい」と指示しています。
新しいバージョンをインストールしただけでは自動で切り替わりませんので、インストール後すぐに使う場合はセットで実行します。

特定のディレクトリ配下でのみ別バージョンを指定することもできます。

```bash
$ cd ~/other_version
$ pyenv local 3.X.X
```
別バージョンを使用したいディレクトリへ移動してlocal設定をすることで指定できます。
上記の例では、「other_versionディレクトリ配下のみ3.X.Xを使用しなさい」と指示しています。

## venv:仮想環境構築ツール
venvとはpython3.3以降のバージョンであればデフォルトで入っている、仮想環境を構築するコマンドラインツールです。
高機能で評価の高いサードパーティアプリのVirtualenvから仮想環境の基本部分だけをPython公式として採用し同梱されたものです。

### 仮想環境の作成
```bash
$ cd ~/TargetDirectory
$ python -m venv <仮想環境名>　
```
仮想環境を作りたいディレクトリへ移動してvenvを実行するとディレクトリ内に仮想環境名のディレクトリが作成され必要な情報が格納されます。
<仮想環境名>は慣例的に'venv'とすることが多ようです。

### 仮想環境をアクティヴ化
```bash
$ source <仮想環境名>/bin/activate
(<仮想環境名>)$
```
venvを実行しただけでは、仮想環境を作成できていても有効化はされていません。アクティブにすることで仮想環境に入れます。
仮想環境下ではプロンプトの前に<仮想環境名>が表示されるようになります。
仮想環境下でpipコマンドを使ってインストールされた各種ライブラリなどは、仮想環境を構築したディレクトリ内でアクティブになっているときのみ利用できます。

### 仮想環境を終了する
```bash
(<仮想環境名>)$ deactivate
$ 
```
仮想環境を抜けるとプロンプト前の仮想環境名が消えます。

### 仮想環境の削除
venvを実行したディレクトリ内の<仮想環境名>ディレクトリを削除するだけです。
競プロの問題をnibblesで解く②

# はじめに
[前回](https://qiita.com/i_taku_/items/e85f9f4ea482e35dfadd)に引き続き、簡単な問題を通してnibblesの解説をしていきたいと思います。
今回はリストの入力を扱いたいと思います。
[リファレンス](https://www.golfscript.com/nibbles/quickref.html)を眺めながら見ていただくと若干わかりやすいかもです。
では、早速問題を解いていきましょう。

今回もフォーマットはkotatsugameさんの[こちらの記事](https://qiita.com/kotatsugame/items/184bfd63d9b21f214475)から、丸パクリさせていただきました。（いつもありがとうございます。）

> 入力形式

解法

```:Byte数
コード
``` 
コメント

# 問題
## [ABC344 B - Delimiter](https://atcoder.jp/contests/abc344/tasks/abc344_b)
> $ A_1 $
> $ A_2 $
> $ \vdots $
> $ A_N $


$A_1, A_2, \cdots A_N$ を $A_N, A_{N-1}, \cdots A_1$ の順に出力します。
```nibbles:2byte
\_
```

最近の問題でちょうど良いものがありました。
nibblesでは「 _ 」で一行目の入力をリストとして取得できます。
また、今回のように数字が一列に並んでいる場合も、例外的に数値をリストとして取得できます。

この性質について、わかりやすさのために、pythonで例を載せておきます。
```python:_
A = list(map(int, input().split())  # 基本これ
A = [int(input()) for _ in range(N)]  # 例外パターン（今回）
```

リストで取れたら後は「 \ 」をつけてreverseしてあげればOKです。

## [JOI 2020/2021 一次予選 (第1回) A - 2 番目に大きい整数](https://atcoder.jp/contests/joi2021yo1a/tasks/joi2021_yo1a_a)
> $A \quad B \quad C$

$A \quad B \quad C$ のうち、2番目に大きい数を出力します。
```nibbles:5byte
=2`<_
```
一行の数字入力ですので「_」を使います。
あとはソート「 `< 」してあげた後に、インデックス指定「 = 」を使用すればOKです。
nibblesはプログラミング言語では珍しく、1-indexedなので = の引数は2にしましょう。
1-indexedの方がコードゴルフの観点では有利でしょうという想いがあるそうです。

ついでに、nibblesのsortの計算量は$O(N^2)$なのでたまに結構辛いです。

## [AGC001 A - BBQ Easy](https://atcoder.jp/contests/agc001/tasks/agc001_a)
> $ A $
> $ L_1 \quad L_2 \quad \ldots \quad L_{2N} $

$L$をソートして、奇数番目の値の和を出力します。
```nibbles:12byte
+`%2`<=2;;$
```
だんだん暗号感が増してきました。
やってることは単純ですので、下記の順に一つずつ見ていきます。
①$ L $をソート
②$L$の奇数番目の値を取得
③和を計算


### ①Lをソート
「 ;;$ 」で数字の行がまとめて取得できます。

pythonで見るとこんな感じ。
```python:;;$
ints = [list(map(int, input().split())) for _ in range(XX)]  # ;;$
```
$L$をソート ⇒ 二行目をソートですのでインデックス指定の「 = 」と合わせて、「 \`<=2;;$ 」となります。


### ②Lの奇数番目の値を取得
奇数番目を取得する際に便利な演算 step があります。
「 `%[数字] [配列] 」を指定すると、配列の要素を数字ステップごとに取得できます。

例として、1~10までのリストを見てみます。
「 , [数字] 」（カンマ＋数字）で、1からのリストを生成できます。

\`%2 ,10 -> 1 3 5 7 9
\`%3 ,10 -> 1 4 7 10
\`%100 ,10 -> 1

今回、$L$の奇数番目を取得したいので、「 \`%2 」がそのまま使えます。

ここまでで作成した
「 \`%2`<=2;;$ 」をテストケース2で実行してみます。

入力
> $ 5 $
> $ 100 \quad 1 \quad 2 \quad 3 \quad 14 \quad 15 \quad 58 \quad 58 \quad 58 \quad 29 $

出力
$ 1 $
$ 3 $
$ 15 $
$ 58 $
$ 58 $

（nibblesでは、配列は勝手に改行区切りで出力してくれます。）
$ L $ をソートした結果は $ 1\quad 2\quad 3 \quad 14 \quad 15 \quad 29 \quad 58 \quad 58 \quad 58 \quad 100 $ なので、期待通りの出力ですね。

### ③和を計算
最後にこの配列の和を取ります。
\+ 演算子は配列を引数に取るとsumを取ってくれるので、\+ を付けて完成です。
```nibbles:12byte
+`%2`<=2;;$
```

# おわりに
[リファレンス](https://www.golfscript.com/nibbles/quickref.html)とにらめっこしながらそれっぽい関数を使ってみる、使い方がわからなかったら[ソース](https://github.com/darrenks/nibbles/blob/main/Ops.hs)の方で詳しく見てみる、そんな感じで解き進めていくのがオススメです。
次回は、map、filterを扱ってみたいと思います。これらはめちゃくちゃ頻出ですが、最初はわかりづらい部分ですので、ぜひ見てみてください。
overflow: hidden の要素内にアンカーリンクのゴールを置くと要素が上にズレることがある

## 事象

タイトルの通り。

gifをご覧ください

![anchor.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704882/282f7f5e-58a2-ad51-5377-6c707250a421.gif)

黒枠の四角には overflow: hidden　がかかっている状態です。
「第2章」の見出しにはidが振られております。

動画のように、アンカーリンクをクリックすると赤丸とその下の第2章部分が上にずれますね。
もちろんこちらの理想は「赤丸の大部分が見えた状態を保ちつつ、」第2章の見出しまで飛んでほしいわけです

## 起こる条件
overflow: hidden をはずしたときに「スクロールバーがでる」時にこれが起こります。
「http~~~/#section2」のようにアクセスするとずれます。

## 何が起こっているのか
overflow: hiddenで切り取る前に、黒枠の四角内で該当位置（第2章の見出し）まで移動してから切り取っているように見えます

## 解決策？
「起こる条件」にも書いた通り overflow: hidden をはずしたときにスクロールバーがでないように余白などを調整してあげれば良さそうです。
それが難しいようなら overflow: hidden の要素の外にアンカーリンクのためのゴールをおいて position: absolute で位置調整をする、などの方法がありますがちょっと嫌ですね


## 最後に
後輩にこの事象についてヘルプを求められたとき、「jsが悪さをしているんじゃないか」と思い調査に30分ぐらい費やしてしまいました。
同じ現象に困っている人が「overflow: hidden」「アンカーリンク」でこの記事をみつけてくてたらいいなと思っています
Savings Plansの共有先アカウントと使用量の確認アプリケーションを作ってみた

## 概要
https://qiita.com/hiroaki_i/items/2ac81024ec3f923ed771

の続きになります。
前回はその方法の共有でしたが、
今回はSAMテンプレートの共有です。


## テンプレート
https://github.com/hiroaki-ito-hulft/monthly-sp-cost-aggregator?tab=readme-ov-file




## 解説
### 出来ること
このSAMでデプロイされるスクリプトでは、
特定の1つのAWS Account IDで購入したSPを追跡できます。
アカウント指定は1つですが、複数SP IDがあっても問題なく、
複数のSPで合計何$そのアカウントに共有されたかが記載されます。

具体的には、以下のようなcsvが得られます。
| Account Id | Account Name | Legal Entity | Amount (USD) |
|:-----------:|:------------:|:------------:|:------------:|
| 111111111111 | Name1 | Amazon Web Services Japan G.K. | 5118.590701425601 |
| 222222222222 | Name2 | Amazon Web Services Japan G.K. | 187.7021327 |
| 333333333333 | Name3 | Amazon Web Services Japan G.K. | 2585.2460987617997 |
| 444444444444 | Name4 | Amazon Web Services Japan G.K. | 12.171609 |
| 555555555555 | Name5 | Amazon Web Services Japan G.K. | 5.379112028 |


### 事前準備
このSAMテンプレートを使用するためには、AWS SAM CLIが必要です。

https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/install-sam-cli.html


CURとAthenaは事前にドキュメントに従い作成し、使用します。

https://docs.aws.amazon.com/ja_jp/cur/latest/userguide/creating-cur.html

https://docs.aws.amazon.com/ja_jp/cur/latest/userguide/cur-query-athena.html

それに加えSavings Plansのアカウント、使用量をまとめたcsvを配置するS3バケットを作成しておきます。

### デプロイ方法
事前準備したAthenaのデータベース名などのパラメータをsamconfig.yamlに渡した後は、
```
sam build -u
sam deploy --resolve-s3
```
のみ実行することでアプリケーションが作成されます。


## 全体のアーキテクチャ図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682172/2015af44-40fa-5a65-1b14-90c421cb1d39.png)




CURとAthena, S3バケットについては事前に作成していますので、
このSAMでは、この中のEventBridge, Lambdaを作成しています。
App StoreにDSAのトレーダーとして連絡先情報を提供する前に読んでほしい

2024年3月21日にAppleより [App Store Connectでのトレーダーステータスの提供要件](https://developer.apple.com/jp/news/?id=x60uzbu9) という案内がありました。

要約すると、EUのデジタルサービス法（DSA）に準拠するため、

* DSAのトレーダーに該当するか確認せよ
* トレーダーに該当する場合はその連絡先情報を表示する必要があるから提供せよ

ということのようです。

おそらくApp StoreからEU向けにアプリを配信している場合はトレーダーに該当することとなり、トレーダーとして連絡先情報をAppleに提供しなければなりません。

### 連絡先情報の提供
まず、このようなフォームを入力する必要があります。住所等の基本的な情報はすでにApp Store Connectに登録済みのものが反映されており、追加で必要なのは連絡先の電話番号とメールアドレスです。

![Qiita_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/91bd4ca5-32dd-74a8-f624-cb1b77baac69.png)

これを入力して終わりかと思いきや、**これらの情報が正しいことを証明する必要があります**。

### メールアドレスの確認
登録したメールアドレスにメールが届くため、そこに記載された Verification Code を入力します。

![Qiita_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/6488847b-8fce-cd63-0264-9188b0448b78.png)

### 電話番号の確認
次は電話番号にSMSのメッセージで Verification Code が届きますので、それを入力します。

![Qiita_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/6044cb86-86cd-6724-5a28-0ce4b0d43d66.png)

SMSの受信はできないケースにおいては **Didn't get a verification code?** のテキストボタンをクリックし、**Call Me** を選択することで、電話呼び出しにて Verification Code を受け取ることができます。

![Qiita_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/4ff683e4-0ad8-41be-4fd7-7d30757ff144.png)

※ 電話呼び出しへの対応も難しい場合は、確認用書類のアップロードを行うオプションもあるようですが、試していません。

(2024/5/2 追記) コメントにて確認書類の提出事例について情報をご提供いただきましたので追記します。 @imk2o さん、ありがとうございました！
* 電話番号確認の後、結局確認書類の提出も求められた
* (確認書類は)画面中の指示では「組織名を確認できるビジネス文書または裁判所文書...」とかなり曖昧だった
* 「履歴事項全部証明書」を提出して対応完了

## 難しいポイント
本件に業務での対応となる場合、所属会社の代表となる電話番号やメールアドレスを入力することになると思います。

つまり、**事前にそれらの電話番号やメールアドレスの対応ができる人・部門と連携して進める必要があります**。

組織構造によってはこれがちょっと大変だったりする場合もあるかと思いますので、この記事を書きました。対応のお役に立てると幸いです。

なお、弊社の場合ですと代表電話番号が自動応答のシステムを利用していたため、総務部門と連携して一時的にそれを無効にして対応しました。
Pythonで「文字列の先頭や末尾などの位置にマッチするパターンを記述する」の動作を確認してみた

# 概要

Pythonで「文字列の先頭や末尾などの位置にマッチするパターンを記述する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/python/regex/index12.html

# 実装

以下のファイルを作成しました。
```sample.py
import re
pattern = re.compile(r'^Red')
print(bool(pattern.search('Red Table')))
print(bool(pattern.search('Reduce speed')))
print(bool(pattern.search('Border Color is Red')))

import re
pattern = re.compile(r'\ARed')
print(bool(pattern.search('Red Table')))
print(bool(pattern.search('Reduce speed')))
print(bool(pattern.search('Border Color is Red')))

import re
pattern = re.compile(r'Script$')
print(bool(pattern.search('JavaScript')))
print(bool(pattern.search('I am studying TypeScript')))
print(bool(pattern.search('PostScript is difficult')))
print(bool(pattern.search('OpenScript\n')))

import re
pattern = re.compile(r'Script\Z')
print(bool(pattern.search('JavaScript')))
print(bool(pattern.search('I am studying TypeScript')))
print(bool(pattern.search('PostScript is difficult')))
print(bool(pattern.search('OpenScript\n')))

import re
pattern = re.compile(r'\bwork')
print(bool(pattern.search('a working person')))
print(bool(pattern.search('Go to see fireworks')))
pattern = re.compile(r'ing\b')
print(bool(pattern.search('a working person')))
print(bool(pattern.search('ingenious design')))

import re
pattern = re.compile(r'\Bam')
print(bool(pattern.search('Difficult program')))
print(bool(pattern.search('full amount')))
pattern = re.compile(r'am\B')
print(bool(pattern.search('full amount')))
print(bool(pattern.search('Difficult program')))
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
True
True
False
True
True
False
True
True
False
True
True
True
False
False
True
False
True
False
True
False
True
False
```

# まとめ

何かの役に立てばと。
canvasにて、マウスによる図形描画を行う

# 概要
単なるcanvas要素に対する図形描画の記事は幾つかありますが、canvas要素に設定されている画像に対して、図形描画を行う記事などが少なかったので、備忘録的な意味も含めて
今回記事にしていきたいと思います。

# 図形描画の要件
・canvas要素に設定されている画像に対して、マウスによって図形描画を行う
・canvas要素をbase64形式で、ダウンロードさせる

# 自分が直面した問題
canvas要素に画像が表示されている状態で、マウスによる図形描画を行いたい。
だがマウスで、丸を描く動き・斜め移動させた場合に、残像が残ってしまい、うまく図形描画ができなかった。
残像を表示させたくなかったので、描画が終わった際に、clearRectでcanvas要素をクリアしていたが、画像もクリアされて表示されなくなってしまう。

# 解決方法
canvasには、レイヤー機能はないので、canvasを２つ重ねる様にして、clearRectで残像を消しても、画像が消えないようにする。
メインレイヤーと描画レイヤーに分けて描画を行う

⚫︎メインレイヤー
・画像はメインレイヤーに設定
 
⚫︎描画レイヤー
・マウスのによる図形描画はこのレイヤーに反映
・mouseupイベントで、メインレイヤーと描画レイヤーをマージ

# 成果物
下記githubのリポジトリに成果物をアップしていますので、気になる方はクローンして実際に動かしてみて下さい。

https://github.com/tixyu10/canvas-shapes-masking

![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247902/8c87c186-bb7f-0e59-228a-2857fc0e4de2.gif)

# 参考にさせていただいた記事
[canvasに長方形を描く](https://knap.jp/blog/canvas_drew_rect)
[[HTML5] 複数のCanvasを合成する](https://blog.katsubemakito.net/html5/canvas-concat)
Route53で購入したドメインを別AWSアカウントに移管する手順


# 1.概要
Route53で購入し登録したドメインを別アカウントに移管するということが可能です。直近で移管作業を行い手順を備忘として残しておくため記事を書きました。

# 2.ドメイン移管の方法
今回は以下のRoute53で購入したドメインを別アカウント
・Route53でドメインを購入している。
・移管元のアカウント、移管先のアカウントを準備している
・移管元のアカウントにて「移管のロック」が無効になっている
・ドメイン登録後14日以内ではないこと


[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/domain-transfer-between-aws-accounts.html)に記載されている内容だとコンソールで行う手順があるためやってみます。
また本作業移管作業の際に対象ドメインを利用しているホストゾーンが一時的に利用できなくなるなどのダウンタイムはないです。

# 3.コンソールでやってみた
Route53のコンソール画面に移動し登録済みドメインをクリックし、移管したいドメインを選択します。

![ドメインクリック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683522/631b664f-ff01-a3fe-d30a-f90bf4b7f351.png)

選択したドメインの画面右上の「別のAWSアカウントに移管」を選択します。
![別アカウントに移管をクリック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683522/64c05ee9-0d2a-676c-2a2a-cd900c71d8ae.png)

移管先AWSアカウントIDを入力する画面が出てくるのでIDを入力します。
![アカウント移管先.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683522/85a9c780-20dd-9d3c-6022-3b62b7b7bb37.png)

その後移管先アカウントで利用するパスワードが発行されるのでメモします。

移管元アカウントの作業は以上で移管先アカウントに移動します。
移管先アカウントのRoute53のリクエスト画面にて該当ドメインを選択し右上の承認を押します。
![承認画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683522/d4dd79d8-aa45-e6d7-dd45-055be5bae9cd.png)

移管を承認する最終画面がでるので、移管元アカウントの作業でメモしたパスワードを入力し「ドメインを移管」を押します。

![移管最終画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3683522/78387314-d8cd-e20f-7d3b-2fb37688b52c.png)

コンソールで行う作業は以上です。
５分ほど経つと移管先アカウントの登録ドメインの画面に移管したドメインが表示されるようになります。

# 4.まとめ
レアケースですがコンソールを用いた別アカウントへの登録ドメインの移管手順でした。
別アカウントへのホストゾーンの移行は追加で別作業が必要になります。[別記事](https://qiita.com/roxas886/items/15d6bb6e92620e752597)に詳細内容記載しているので実施する際は参考にしていただけたらと思います。
【SwiftUI】端末の音量を強制的に変更する方法【iOSアプリ】

[この記事](https://sinn246.wordpress.com/2018/07/12/ios-11-4%E3%81%A7mpvolumeview%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E9%9F%B3%E9%87%8F%E5%A4%89%E6%9B%B4%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F%E4%BB%B6/)によると、iOSはアプリから端末の音量を操作できないようになっているそうだ。
しかし、[StackOverflow](https://stackoverflow.com/questions/33168497/ios-9-how-to-change-volume-programmatically-without-showing-system-sound-bar-po/50740234#50740234)を参考にすると、無理やりではあるが、音量を変更できるそうだ。その方法と注意点を紹介する。


* Swift 5
* Version 15.3
* iOS17.3で動作確認

さっそく、そのコードを見てほしい。

### コード
```swift
import MediaPlayer

extension MPVolumeView {
    static func setVolume(_ volume: Float) -> Void {
        let volumeView = MPVolumeView()
        let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { //(1)
            slider?.value = volume
        }
    }
}
```
このように、MPVolumeViewを拡張して、

### 使い方
```swift
MPVolumeView.setVolume(0.6)//(2)
```
このように使うだけである。

* (1) +0.1としているのがミソで、slider?.value = volumeとするのを少し遅らせることで音量を変更できる。
* (2) 0.6としているところは、音量を表す。音量は0.0〜1.0の範囲で指定でき、値が大きいほど音量も大きくなる。


※この方法は、制限を強行突破しているため、いつ動かなくなってもおかしくないです。

# 参考
https://sinn246.wordpress.com/2018/07/12/ios-11-4%E3%81%A7mpvolumeview%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E9%9F%B3%E9%87%8F%E5%A4%89%E6%9B%B4%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F%E4%BB%B6/

https://stackoverflow.com/questions/33168497/ios-9-how-to-change-volume-programmatically-without-showing-system-sound-bar-po/50740234#50740234
PowerMacG4をATX電源で延命させる。

長年使っているPowerMacG4の電源が昇天したとの連絡があり「動くようにしてほしい」と依頼がありました。
純正(Apple製)の電源ユニットの入手が困難なためATX電源をつなげるための変換ケーブルを用意しました。
その備忘録です。

:::note info
警告
PC/Mac電源の改造は事故の原因になります。
本記事をもとに行った結果の責任は取りかねます。
この記事は改造を推奨するものではありません。
:::

# 対象の機体(ハードウェア)
- PowerMacG4 (以後、MDD)
「Mirrored Drive Doors/FW800」です。
![MDD](https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Apple_PowerMac_G4_M8570_MDD_front.jpg/220px-Apple_PowerMac_G4_M8570_MDD_front.jpg "Wikipediaより")
(Wikipediaより)

## 事前調査
PowerMacG4の電源コネクタのPin配列と、ATX電源のPin配列の確認。
![PIN_ATX_MDD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3144706/d29157ea-9a52-1a36-0426-93f9b92157ba.png)


## ケーブル制作にあたって
以下の内容で加工した
* 電源ケーブルを切断直接加工せず延長コードを加工
![ATX_cable](https://m.media-amazon.com/images/I/71qWgycM8+L._AC_SL1500_.jpg)
* ATX側の[PWR_OK] [+5.0V]×2 はMDD側に不要なのケーブル自体を取り外す
（カットではショートの原因になるため）
* [+12.0V]はATX側:2カ所 => MDD側:4カ所 のため2本を分岐して4本にする
* [GND]はATX側:8カ所 => MDD側:9カ所 のため1本を分岐して9本にする

## ...で、完成。
![PXL_20240311_141402548.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3144706/91067247-d34c-6f54-14d9-04457da7d498.jpeg)
分岐は圧着端子を使いました。

Macに接続して作動を確認した。
![PXL_20240312_112014613.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3144706/01908ace-896d-7c10-f02a-faa4c729c5b6.jpeg)

分かっていたものの、カーバーが閉じないためワイヤーでカバーを保持するように固定し完了。
![432380726_10232844068146619_8450206536948275075_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3144706/6ca357d4-4222-be50-4972-5025076e50ff.jpeg)
ChatGPTを便利にするChrome拡張機能

## Chathub
https://chathub.gg/ja
複数のAIチャットを同時に使える拡張機能。
1つだけのAIだとハルシネーションが分からないが、複数比較することで防ぐなんてこともできる。
有料版(35ドル買い切り)が複数のAIチャットを同時に使えるのでオススメ。

## ChatGPT Ctrl+Enter Sender
https://chromewebstore.google.com/detail/chatgpt-ctrl+enter-sender/gbncgdhklmnckojlibfhdadpfbcdbnch?hl=ja

Enterキー問題を解決してくれる拡張機能。
通常、Enterキーを押すと送信されるが、それが改行になる。
送信する場合は、Ctrl(Command)+ Enterで実行可能。
間違って送信することがなくなるので、超便利。
三次元の直方体の問題でDesmosを使ってサンプルを描画する方法

# Desmosで直方体を書いてみる
```
制約1{制約2{制約3}
```
のように書くといい感じに作成してくれます

https://atcoder.jp/contests/abc312/tasks/abc312_e
この問題のサンプルを作成してみます
```
4
0 0 0 1 1 1
0 0 1 1 1 2
1 1 1 2 2 2
3 3 3 4 4 4
```
![GJRDbNWawAAZfj-.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3701202/0746b71a-18b0-13fd-7a1f-9a97a508b049.jpeg)

![GJRDqN3bkAA5R2X.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3701202/8d2e731d-65f0-d012-eaa0-50f774cf4549.jpeg)

このようになりました、好きな方向から図形を眺めることができるので非常に便利です。これを使うことで三次元の問題で理解しにくい問題文が理解しやすくなると思います。上であげた例題の
```
各iに対し
i番目の直方体の表面とj番目の直方体の表面の共通部分の面積が正であるものの個数を求めてください。
```
の部分がDesmosで実際に図形にしてみると各iについてiともう一つの直方体がくっついている個数を求めればよい。というのがわかりやすいと思います。
なお、4つ直方体を作成しただけで多少動作が重たくなっているので、たくさんの図形を作成しようとすると動作が重たすぎて使いにくくなるかもしれません。



# 上の図形のリンクを置いておきます
https://www.desmos.com/3d/d6a2e5b363

# 別の三次元の問題
直方体とタイトルなどに書いてありますが、立方体でも作ることができます。練習として以下の問題のサンプルを作ってみてもいいかもしれません。もしDesmosを使って考察をすれば0~14を全探索するのがダメである理由に気づきやすいかも...?
https://atcoder.jp/contests/abc343/tasks/abc343_e

E869120さんが投稿していた0~14の全探索がダメなパターンを載せておきます。正直Desmosを使っても思いつきにくいと思います()どちらかというとダメなパターンを教えてもらってそれを手元で確認する、という用途に使うのが多そうです。
https://x.com/e869120/status/1763931692245688445?s=20
![GJRG0w4bgAAMWNX.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3701202/64d14197-7532-ab50-6078-9d973f05f026.jpeg)
_e
Anime Recommendations Databaseのアニメタイトルを日本語化する

# はじめに
今回はAnime Recommendations Databaseというオープンデータの英語アニメタイトルを日本語のもの変換した方法（力技）と、実際に対訳に使えるJSONファイルを公開します。

## データセット
https://www.kaggle.com/datasets/CooperUnion/anime-recommendations-database

# 方法
ChatGPTにぶち込みました。時間がかかるので、一部はClaudeにも入れました。
GeminiとCopilotはプロンプロトが悪いのかうまくいきませんでした。

## 前準備
上記のオープンデータからタイトル一覧を取得し、titles.txtとして保存しました。
これをGPTに渡します。
```python
titles = df_anime[df_anime["視聴タイプ"]=="TV"]["タイトル"].tolist()
with open("titles.txt", "w") as file:
    for title in titles:
        file.write(title + "\n")
```

## 使用したプロンプト
以下のプロンプトを入力したうえで、[W]を押していくと自動で翻訳が作られます。

```markdown
#ゴール
titles.txtの中にある英語タイトルのアニメタイトルを日本語タイトルに変換する

#条件
- #手順 に従って行うこと
- CSVファイルのみ出力する
- やり取りは日本語で行う
- 説明は出力せず、「変換を行います」と話す

#手順
1. 「読み込みを行います」と出力
2. 先頭から40行を読み込む
3. 「次に変換を行います」と出力
4. #出力例 を参考にして先頭から40行分の英語タイトルを日本語タイトルに変換できるように辞書型で出力する
5. 「次に進む（W）」かどうかを聞く．
6. 次に進む場合には41行目から80行目までを読み込み，手順3へ戻る。
- この手順を3787行まで、95回繰り返す

#出力例
{
    "Fullmetal Alchemist: Brotherhood":  "鋼の錬金術師 FULLMETAL ALCHEMIST",
    "Gintama°": "銀魂°",
    # 以下省略、全てのタイトルをこのリストに追加
}
```

## 結合
一つずつJsonで保存していたので、これらを結合させます。
```python
import os
import json

folder_path = "日本語訳リスト"

json_files = [file for file in os.listdir(folder_path) if file.endswith(".json")]

combined_data = {}

for file in json_files:
    file_path = os.path.join(folder_path, file)
    with open(file_path, "r", encoding="utf-8") as f:
        try:
            data = json.load(f)
            combined_data = {**combined_data, **data}
        except:
            print("Error reading file:", file)
            continue

output_file = "combined_data.json"
with open(output_file, "w", encoding="utf-8") as f:
    json.dump(combined_data, f, ensure_ascii=False, indent=4)

print("Combined data saved as", output_file)
```

# GitHubで公開しています

使用したい方は使ってください。
（ファイルの行数が多いのでリンクにしています）

Anime Recommendations Databaseの日本語訳 by sugimochi97
[https://gist.github.com/sugimochi97/76313f26b0c88e8db86f598534503354](https://gist.github.com/sugimochi97/76313f26b0c88e8db86f598534503354)
AWS の s3 で別アカウントで見えるように

# 概要

AWS のs3 のバケットを別アカウントで見えるようにする手順のメモ

# 手順

AccountA (以降【A】) から AccountB（以降【B】）に公開するものとする。

1. 【A】に `bucket-a` 作成。ファイルを配置。
1. 【A】の `bucket-a` のバケットポリシーで下記を追加（【B】の root に対して公開）:
   - `aa/` 以下に List 限定
   - `aa/aa1/` 以下は読み取り専用
   - `aa/aa2/` 以下は読み書き可能
   ```json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "OpenToBToList",
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::{BのアカウントID}:root"
          },
          "Action": "s3:ListBucket",
          "Resource": "arn:aws:s3:::backet-a",
          "Condition": {
            "StringLike": {
              "s3:prefix": "aa/*"
            }
          }
        },
        {
          "Sid": "OpenToBToReadOnly",
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::{BのアカウントID}:root"
          },
          "Action": "s3:GetObject",
          "Resource": [
            "arn:aws:s3:::backet-a/aa/aa1/*"
          ]
        },
        {
          "Sid": "OpenToBToReadWrite",
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::{BのアカウントID}:root"
          },
          "Action": [
            "s3:GetObject",
            "s3:PutObject",
            "s3:PutObjectAcl",
            "s3:DeleteObject"
          ],
          "Resource": [
            "arn:aws:s3:::backet-a/aa/aa2/*"
          ]
        }
      ]
    }
   ```
1. 【B】のユーザに下記のポリシーを適用（【B】の root が個別のユーザに対してアクセスを許可）:
   ```json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "CrossAccessToA",
          "Effect": "Allow",
          "Action": [
            "s3:ListBucket",
            "s3:GetObject",
            "s3:PutObject",
            "s3:PutObjectAcl",
            "s3:DeleteObject"
          ],
          "Resource": [
            "arn:aws:s3:::backet-a",
            "arn:aws:s3:::backet-a/*"
          ]
        }
      ]
    }
   ```
1. 【B】から下記実行:
   ```bash
   aws s3 ls s3://bucket-a/aa/
   ```

# 注意

- `aws s3 ls` ではバケット名は出て来ない。コンソールのバケット一覧にも出てこない。
- Admin の権限でアクセスするならユーザのポリシーは関係ない（テストするときには注意）。


# おまけ - WinScp から上記に繋ぐ場合の設定

- `転送プロトコル`: `Amazon S3`
- `ホスト名`: `s3.amazonaws.com`
- `ポート番号`: `443`
- `設定` > `ディレクトリ` > `リモート ディレクトリ`: `/bucket-a/aa/`


# 参考

- [例 2: バケット所有者がクロスアカウントのバケットのアクセス許可を付与する - Amazon Simple Storage Service](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/example-walkthroughs-managing-access-example2.html)
- [WinSCPでAmazon S3に接続してみた | DevelopersIO](https://dev.classmethod.jp/articles/connected-to-s3-with-winscp/)
[Laravel10] JavaScriptのメソッドが読み込まれなかった時の解決事例。（changeイベントハンドラ）

今回は、`Laravel10` で `JavaScript` のメソッドが読み込まれなかった時の解決事例をご紹介します！

## 開発環境
- Laravel10
- aws cloud9

## 前提
## 課題
- `Laravel` のプロジェクトで `vite` を利用し `JavaScript` で記述をしたところ、基本的には問題なく作動しましたが、1つのメソッドだけが実行されませんでした。🤷‍♂️
- 実行されなかったメソッドは、私が定義した `loadImage()` メソッドです。
- メソッドの実行は、`html` の `<input>` タグの `onchange` 属性で行っています。


```html
<!-- 修正前のhtmlの記述 -->

<div class="post_image">
    <input type="file" name="image" accept="image/*" onchange="loadImage(this);"/> <!-- onchange属性-->
    <div id="preview"></div>
</div>
```

```javascript
// 修正前のjavascriptの記述

function loadImage(obj)// loadImage()メソッド
{
    const preview = document.querySelector("#preview");
    
    preview.insertAdjacentHTML("beforebegin", "<p>プレビュー</p>");
    
    for (let i = 0; i < obj.files.length; i++) {
        const fileReader = new FileReader();
        
        fileReader.onload = (event) => {
            document.querySelector("#preview").insertAdjacentHTML("afterbegin", '<img src="' + event.target.result + '"/>');
        };
        
        fileReader.readAsDataURL(obj.files[i]);
    }
}
```
## 解決事例
- `onchange` 属性を使わない方法を取りました。😊
- `html` の `<input>` タグに `id="imageInput"` をもたせ、JavaScriptファイルで `change` イベントハンドラーを使用しました。
- 具体的な記述は以下の通りです。

```html
<!-- 修正後のhtmlの記述 -->

<div class="post_image">
    <input type="file" name="image" accept="image/*" id="imageInput"/><!-- onchange属性->id属性-->
    <div id="preview"></div>
</div>
```

```javascript
// 修正後のjavascriptの記述

function loadImage(obj)// 変更なし
{
    const preview = document.querySelector("#preview");
    
    preview.insertAdjacentHTML("beforebegin", "<p>プレビュー</p>");
    
    for (let i = 0; i < obj.files.length; i++) {
        const fileReader = new FileReader();
        
        fileReader.onload = (event) => {
            document.querySelector("#preview").insertAdjacentHTML("afterbegin", '<img src="' + event.target.result + '"/>');
        };
        
        fileReader.readAsDataURL(obj.files[i]);
    }
}

const imageInput = document.querySelector("#imageInput");// 追加
imageInput.addEventListener("change", function() {
    loadImage(this);
});
```
## 説明
- `onchange` 属性が使えない理由を調べましたが、分かりませんでした。😢
- 公式ドキュメントにで `onchange` で検索したところ `onchange` はヒットしなかったため、`onchange` 属性が古い記述方法なのかもしれません。
## 結論
- ひとまず、`onchange` 属性は使いません！
## 追記（2024/3/28）
コメントで `「type="module"」` というキーワードをいただいたので、再度、修正してみました！
```html
<head>
 <!-- 追記-->
<script type="module">{!! Vite::content('resources/js/preview.js') !!}</script>
</head>
```
残念ながら解決できませんでした。
以下、コンソールのエラーです。

**create:158 Uncaught ReferenceError: loadImage is not defined
    at HTMLInputElement.onchange (create:158:99)**
    
何か手違いがございましたらご指摘いただけると幸いです。🙇‍♂️
break文の使い方

Javaにおけるbreakの概要をまとめます。

目次
[1.break文とは](#1-break文とは)
[2.breakの使い方](#2-breakの使い方)

# 1. break文とは
break文は、実行されると繰り返し処理を終了して、次の処理へ移ってくれる便利なものです。

以下のように記載します。

```java
break;
```

繰り返し処理であるfor文やwhile文の他、switch文でも使用できます。

# 2. breakの使い方
for文の中にif文を書き、ifの条件式がtrueのときに実行される処理としてbreak文を書くと、for文の条件式を全て実行せずに処理を終わらせることができます。
```java
int num = 10;

for (int i = 0; i < 10; i++){
  num -= 3;
  if (num < 0){
  break;
  }
}
```
上記コードのfor文は10回繰り返す条件式になっていますが、if文の条件式とbreak文によって、実行回数が10回に満たなくとも、numが0より小さくなった場合に処理が終わり、次の処理へ移行するようになっています。
Web API The Good Partsのまとめ Part2

# APIの設計

## エンドポイントの設計とリクエスト形式


- 何をAPIとして公開するか決めよう
    - サービスのコアとなる機能を選ぶ
    →そのサービスの価値を生んでいるもの
    ex)ECサイト…商品の検索・購入
    
- URIのポイント
    - 短く入力しやすい
    - 人間(開発者)が読んで分かりやすい
    - 大文字小文字が混在していない
        - 基本は小文字
        - 大文字は404で返すケースが多い
    - 改造しやすい
    - サーバのアーキテクチャが反映されていない
        - 脆弱性をつかれるリスクがある
    - ルールが統一されている

- METHODについて
    - GET、POSTが多い（HTMLのフォームでもこの2つしか使えない）
    - POSTは本来新規情報の作成に使うべきで、情報の更新や削除には別のメソッドが適している。
    - X-HTTP-METHOD-Overrideヘッダ
        - 仕様でGETとPOSTメソッドしか使えない場合、本当に使いたいメソッドを記述するヘッダ
    - _methodパラメータ
        - X-HTTP-METHOD-Overrideヘッダ同様に本当に使いたいメソッドを記述するパラメータ
        - Ruby on Railsで使用されている



### WebAPI設計の基本

<aside>
🔑 「あるデータの集合」と「個々のデータ」をエンドポイントとして表現し、それに対してHTTPのメソッドで操作を表していく

</aside>

### エンドポイント設計で注意すべきこと

1. 複数形の名詞を利用する
2. 利用する単語に気を付ける
3. スペースやエンコードを必要とする文字を使わない
4. 単語をつなげる必要がある場合はハイフンを利用する
    - _(アンダースコア)だとリンクアドレスに下線が引かれた場合見づらい
        - profile_image

### 検索とクエリパラメータの設計

- データ一覧を取得するエンドポイントに絞り込みをかけて検索させる
    - 絞り込みするのに必要なのがクエリパラメータ
- クエリパラメータの取得数と取得位置
    - page/per_pageやlimit/offsetなどが一般的
    - limit/offsetの方が自由度が高い
        - これらは取得位置を相対的に指定するものだが、これには
            1. データ量が増えれば増えるほど時間がかかる
            2. 更新頻度の高いデータの場合、データの不整合が起こりうる
            という問題点がある。
Proxy環境下でAWS SDKv3 for JavaScriptを使う

AWS SDKでAmazon CloudSearchを利用する際にどハマリしたので備忘録として作成。
~~ずっと認証情報が渡せてないと勘違いしてたのは内緒~~

## 環境
```
$ node --version
v21.7.1
$ yarn --version
1.22.19
```

## 必要パッケージのインストール
```
$ yarn add @aws-sdk/client-cloudsearch-domain @aws-sdk/credential-provider-ini @smithy/node-http-handler https-proxy-agent dotenv
```

- @aws-sdk/client-cloudsearch-domain : Amazon CloudSearchに検索リクエストを実行
- @aws-sdk/credential-provider-ini : `~/.aws/credentials`からAWSの認証情報を読み込む
- @smithy/node-http-handler : HTTPリクエストハンドラ
- https-proxy-agent : プロキシ経由で通信を行う
- dotenv : `.env.local`から設定情報を読み込む
## 実装例

接続で利用する認証情報は`~/.aws/credentials`に予め設定しておきます。
```~/.aws/credentials
[default]
aws_access_key_id = xxxxxxxxxxxxx
aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxx
```

`.env.local`に設定したPROXYからプロキシ情報を読み込むものとします。
今回は接続に必要な情報もここで定義します。
```.env.local
PROXY=http://example.com:port
AWS_REGION=your-region
ENDPOINT=https://search-your-cloudsearch-domain.your-region.cloudsearch.amazonaws.com
```

```typescript:App.ts
import { CloudSearchDomainClient, SearchCommand } from "@aws-sdk/client-cloudsearch-domain";
import * as dotenv from 'dotenv';
import { fromIni } from '@aws-sdk/credential-provider-ini';

import { NodeHttpHandler } from "@smithy/node-http-handler";
import { HttpsProxyAgent } from "https-proxy-agent";

// .env.localの内容を読み込む
dotenv.config({ path: '.env.local' });
const region: string = process.env.AWS_REGION ?? '';
const endpoint: string = process.env.ENDPOINT ?? '';
const proxy: string = process.env.PROXY ?? '';

// プロキシ情報の設定
const agent = new HttpsProxyAgent(proxy);

// 認証情報の読み込み
const credentials = fromIni({ profile: 'default' });

// CloudSearchDomainClientの設定。
let csClient: CloudSearchDomainClient | null = null;

// まだ一度も呼びだされていない場合はcsClientを初期化し返却、
// 呼び出し済の場合は初期化済みのcsClientを返却する。
async function getClient(): Promise<CloudSearchDomainClient> {
  if (!csClient) {
    const creds = await credentials();
    csClient = new CloudSearchDomainClient({
      // requestHandlerにプロキシ設定済みのHttpsProxyAgentを渡す。
      requestHandler: new NodeHttpHandler({
        httpAgent: agent,
        httpsAgent: agent,
      }),
      // 接続に必要な情報をここで渡す
      endpoint: endpoint,
      region: region,
      credentials: creds,
    });
  }
  return csClient;
}

// 検索結果をコンソールに出力する。
async function search(query: string) {
    const client = await getClient();
    const command = new SearchCommand({
      query: query,
    });

    try {
      const response = await client.send(command);
      // 検索結果はresponse.hits?.hit[]に格納されます
      console.log(JSON.stringify(response));
    } catch (error) {
      console.log(JSON.stringify(error));
    }
}

search('hogehoge');
```

**実行結果**
```json
{
	"$metadata": {
		"httpStatusCode": 200,
		"attempts": 1,
		"totalRetryDelay": 0
	},
	"hits": {
		"found": xx,
		"start": 0,
		"hit": [
			{
				"id": "id",
				"fields": {...}
			}, ...
		]
	}
}
```
ES module 内では、import "file.mjs" でなく、import "./file.mjs" にする必要がある (カレントディレクトリであっても)

```sh
├── test.mjs
└── test2.mjs
```

この構成で、`node test.mjs`を実行する際のインポートは、

```js:test.mjs
import "test2.mjs" // だめ
import "./test2.mjs" // OK
```
x*(x+1)*(x+2)*(x+3)の最小値「2024 早稲田大学 人間科学部【１】(1)」をChatGPTとsympyでやってみたい。穴埋め (ア)のMathMLの対応。

・穴埋め (ア)のMathMLの対応。
・ChatGPT-3.5先生へ。sympy回答のおすすめキーワード　**本当ですか**　アキラメマシタ
　私の質問のしかたが悪いですか？

# オリジナル
大学入試数学問題集成 様＞【１】(1) テキスト

https://mathexamtest.web.fc2.com/2024/202413591/2024135910400mj.html

公式ホームページ
https://www.waseda.jp/fhum/hum/assets/uploads/2024/02/24_19_ans.pdf#page=5
https://www.waseda.jp/inst/admission/other/2024/02/21/15794/

# wolframalphaで
・グラフがでます。

https://www.wolframalpha.com/input?i=x*%28x%2B1%29*%28x%2B2%29*%28x%2B3%29%E3%81%AE%E6%9C%80%E5%B0%8F%E5%80%A4


# ChatGPT-3.5先生へ
・大学入試数学問題集成 様のMathML
```
<p class="s1level"><a name="q-0401" 
id="q-0401"></a><span 
class="qnum">【１】</span><a name="s-0401" di="s-0401"></a><span 
class="shomon1">(1)</span>　<math>
<mi>x</mi><mspace width=".2em"></mspace>
</math>が実数であるとき，<math>
<mrow><mi>x</mi><mo>&it;</mo><mo stretchy="false">(</mo><mi>x</mi>
<mo>+</mo><mn>1</mn><mo stretchy="false">)</mo><mo>&it;</mo>
<mo stretchy="false">(</mo><mi>x</mi><mo>+</mo><mn>2</mn><mo stretchy="false">)</mo>
<mo>&it;</mo><mo stretchy="false">(</mo><mi>x</mi><mo>+</mo><mn>3</mn>
<mo rspace=".2em" stretchy="false">)</mo></mrow>
</math>の最小値は<math>
<mspace width=".2em"></mspace><mrow class="b1box"><mspace width=".2em"></mspace>
<mtext class="futoji">ア</mtext><mspace width=".2em"></mspace></mrow>
<mspace width=".2em"></mspace>
</math>である．
</p>
```
回答
英語です
```
さいしゅうぎょうに、いかをついかします。
sympyで
```
回答しょうりゃく。こぴーこーどです。
**？？？ 一回目は、間違っています。** 以降も
```Python
from sympy import symbols, Interval, solve, diff

# 変数の定義
x = symbols('x', real=True)

# 式の定義
expr = (x*(x+1)*(x+2)*(x+3))

# 最小値を求めるための導関数の計算
expr_diff = diff(expr, x)

# 極値を求める
critical_points = solve(expr_diff, x)

# 定義域内の極値と端点での値を評価して最小値を求める
candidate_values = [expr.subs(x, cp) for cp in critical_points]
endpoints_values = [expr.subs(x, endpoint) for endpoint in [Interval(-3, float('inf')), Interval(-2, float('inf')), Interval(-1, float('inf')), Interval(float('-inf'), 0)]]
all_values = candidate_values + endpoints_values
min_value = min(all_values)

print("最小値:", min_value)
```

You
**本当ですか**
しょうりゃく
**-1になりませんか**

・SymPy Liveで(PCで。タブレットで実行できません。実行 行？が表示されません。)

https://live.sympy.org/

**アキラメマシタ**

# sympyで(いつもの方法で)

```python
from sympy import *
var('x',real=True)
y=x*(x+1)*(x+2)*(x+3)
print("# ",minimum(y,x))
print("# ",minimum(y,x).simplify())
#  (-3/2 - sqrt(5)/2)*(1/2 - sqrt(5)/2)*(3/2 - sqrt(5)/2)*(-sqrt(5)/2 - 1/2)
#  -1
from sympy.plotting import plot
plot(y,(x,-4,1),aspect_ratio=(1.0,1.0))
# 
print("# ",solve(Eq(y,minimum(y,x).simplify()),x))
#  [-3/2 - sqrt(5)/2, -3/2 + sqrt(5)/2]
```

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/6f770033-0b30-cba9-7772-ffeee3934d9a.png)


# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)
Slackの認証コードをGASで自動化【Google Apps Script】

件名に`Slack の確認コード`が含まれるメールを返却します。デプロイからウェブアプリでデプロイすることで認証の自動化できます。Slack以外の認証にも応用できるかもしれません

```javascript:コード.gs
// その他のプロパティ https://developers.google.com/apps-script/reference/gmail/gmail-message?hl=ja
function messageToObject(message) {
  return {
    date: message.getDate(),
    subject: message.getSubject(),
    plainBody: message.getPlainBody(),
  }
}

// in:anywhereで迷惑メールも検索できる
// newer_than:1d 直近24時間以内のメール
function doGet() {
  const response = GmailApp.search('in:anywhere newer_than:1d subject:"Slack の確認コード"').flatMap(thread => thread.getMessages().map(messageToObject))
  return ContentService.createTextOutput(JSON.stringify(response, null, 2)).setMimeType(ContentService.MimeType.JSON)
}
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/82ff1cd8-a5a8-96fb-7bdd-1614c3ecc733.png)


```javascript
const gas_url = 'https://script.google.com/macros/s/.../exec'
const messages = await fetch(gas_url).then(r=>r.json())
console.log(messages)
```


Messageオブジェクト

https://developers.google.com/apps-script/reference/gmail/gmail-message?hl=ja
Springでのインジェクション方法まとめ

## はじめに

インジェクションの方法は以下の3通り
・**コンストラクタインジェクション（推奨）**
・フィールドインジェクション（非推奨）
・セッターインジェクション

Spring公式によるとコンストラクタインジェクションを推奨しており、フィールドインジェクションは非推奨となっている。
私がこれまで経験した開発現場ではフィールドインジェクションを利用していることが多いため、今後はコンストラクタインジェクションを積極的に利用したい。

## DIについて
Dependency Injectionの略称。
Java固有の概念ではなくあらゆる言語やフレームワークで広く使われている。

大まかに以下の流れで、インスタンスの注入を行う
1. SpringがDIする対象のインスタンスを探す
2. @Autowiredアノテーションが付与されている箇所に、インスタンスを注入する
3. インスタンスのライフサイクルの生成と破棄

本記事はインジェクションの方法に焦点を当てるため、DI詳しい解説は省く。
DIについて以下参照。
[依存性の注入](https://tech-blog.yayoi-kk.co.jp/entry/2022/12/09/000000)


## インジェクションの方法
インジェクションの方法ごとに簡単なソースコードを記載した。

### コンストラクタインジェクション
注入するインスタンスをコンストラクタで受け取る。

```java:ExampleController.java
@RestController
public class ExampleController {

	private final ExampleService exampleService;
	
	// コンストラクタインジェクション（推奨）
	@Autowired
	public ExampleController(ExampleService exampleService) {
		this.exampleService = exampleService;
	}
	
	@GetMapping("/example")
	public void hoge () {
		exampleService.foo();
	}
}
```

メリット
　・フィールド変数をfinalにできる。（変数を上書きさせない）
　・注入するインスタンスをモックオブジェクトに置き換えることが容易で、テストコードが書きやすくなる。

デメリット
　・依存するインスタンスが増えるほど、コンストラクタの記載が冗長になり可読性が落ちる。

### フィールドインジェクション
注入するインスタンスをフィールド変数で受け取る。
```java:ExampleController.java
@RestController
public class ExampleController {
	
	// フィールドインジェクション（非推奨）
	@Autowired
	private ExampleService exampleService;
	
	@GetMapping("/example")
	public void hoge () {
		exampleService.foo();
	}
}
```

メリット
・コードが簡潔で可読性が高い。

デメリット
・フィールドをfinal化できない。（変数の上書きが可能。）
・注入するインスタンスをモックオブジェクトに置き換えが難しく、テストコードが書きづらい。

### セッターインジェクション
注入するインスタンスをSetterで受け取る。

```java:ExampleController.java
@RestController
public class ExampleController {
	
	private ExampleService exampleService;
	
	// セッターインジェクション
	@Autowired
	public void setExampleService (ExampleService exampleService) {
		this.exampleService = exampleService;
	}
	
	@GetMapping("/example")
	public void hoge () {
		exampleService.foo();
	}
}
```

メリット
　・注入するインスタンスをモックオブジェクトに置き換えることが容易で、テストコードが書きやすくなる。

デメリット
　・finalでないため、外部から上書きされる。
　・依存するインスタンスが増えるほど、Setterの記載が冗長になり可読性が落ちる。

## Lombokアノテーションで可読性を上げる
コンストラクタインジェクションを利用するうえで課題になってくるのが、注入するインスタンスの数が増えるとコードの可読性が落ちることだ。
そこでLombokアノテーションを利用することで、コンストラクタの記載を簡潔にすることができる。

```java:ExampleController.java
// 引数付きのコンストラクタを自動生成するLombokアノテーション
@RestController
@RequiredArgsConstructor
public class ExampleController {
	
	// コンストラクタの記載を省略。フィールド変数でインスタンスの注入を行う。
    // @Autowiredも省略できる。 
	private final ExampleService exampleService;
	
	@GetMapping("/example")
	public void hoge () {
		exampleService.foo();
	}
}
```

フィールドインジェクションのように記載が簡潔になり、デメリットであった可読性の低下を軽減を両立できる。
元々のメリットだったフィールド変数が上書きされないことと、テストコードを書きやすさを維持できる。
したがって、インジェクションはコンストラクタインジェクションで行うべき。


## 参考文献
[インジェクションの方法](https://qiita.com/yuto-hatano/items/69d01343f710117e4243)
【CSS】transformプロパティ入門

# はじめに
自身がWebサイトの作成を行ったときに
CSSでサイトに動きを付けるのに役に立った`transform`プロパティについて
基本と応用のいくつかを紹介していきたいと思います。

## transformプロパティについて
CSSの`transform`プロパティは、要素に回転、スケール、移動、傾斜などの変形を適用するために使用できます。

## 基本的な活用
`transform`プロパティはさまざまな関数を利用することで、要素に変形を適用します。
では、いくつか基本的な関数を紹介します。

`translate(x, y)`: 要素を水平（X軸）または垂直（Y軸）に移動させる。
`scale(x, y)`: 要素のサイズを拡大または縮小させる。
`rotate(angle)`: 要素を指定した角度で回転させる。
`skew(angle-x, angle-y)`: 要素を傾斜させる。

:::note info
 `angle`について
`angle`は CSS のデータ型で、度、グラード、ラジアン、周の値で表される角度の値を表します。
単位としては
`deg`,`grad`,`rad`,`turn`などがあります。
:::

例
```css:CSS
.example {
  transform: translate(50px, 100px);
  }
/*要素を右に50ピクセル、下に100ピクセル移動させる。*/
.example {
  transform: scale(1.5);
  }
/*要素を1.5倍に拡大させる。*/
.example {
  transform: rotate(45deg);
  }
/*要素を45度回転させる。*/
.example {
  transform: skew(30deg, 20deg);
  }
/*要素をX軸とY軸に沿ってそれぞれ30度と20度傾ける。*/
```

### 上記の関数は組み合わせることも可能
例
```CSS:CSS
.example{
  transform: translate(50px, 100px) scale(2) rotate(30deg);
  }
/*要素を右に50px、下に100px移動させ、2倍に拡大し、30度回転させる。*/
```

## 3D変形も可能
`transform`プロパティは、3D変形もサポートしています。
この変換は三次元ベクトルであることが特徴です。
座標は要素がそれぞれの方向にどれだけ移動するかを定義します。

`translate3d(x, y, z)`: 要素を3D空間内で移動させる。
`scale3d(x, y, z)`: x,y,z軸に沿って要素を拡大縮小させる。
`rotateX(angle)`, `rotateY(angle)`, `rotateZ(angle)`: 要素を特定の軸周りで回転させる。

例　3D平行移動
```CSS:CSS
.example{
  transform: translate3d(100px, 50px, 200px);
  }
/*要素をX軸方向に100ピクセル、Y軸方向に50ピクセル、Z軸方向に200ピクセル移動させる。*/
```


## 応用的な活用「html要素の＜button＞と組み合わせよう」
`<button>`に`transform`プロパティを使って
インタラクティブなボタンを作成してみましょう。(疑似クラスの`:hover`,`:active`も使用)

htmlで`<button>`を作成したら
基本的なボタンのスタイルを簡単に設定します。
このスタイルでは、ボタンにパディング、背景色、テキストの色、
フォントサイズを設定しています。
また、`transition` プロパティを使って `transform` の効果を滑らかにしています。
```CSS:CSS
.button {
  padding: 10px 20px;
  border: none;
  background-color: #4CAF50;
  color: white;
  font-size: 16px;
  cursor: pointer;
  transition: transform 0.3s;
  }
```
ボタンのスタイルが設定出来たら
次に、ユーザーがボタンにマウスオーバーした時の変形効果を追加してみましょう。
このコードでは、ボタンにマウスオーバーした時、ボタンを10%拡大しています。
```CSS:CSS
.button:hover {
  transform: scale(1.1);
  }
```
さらにさらに
クリック時の変形効果も追加してみましょう。
このコードでは、ボタンがクリックされたときに、ボタンを90%の大きさに縮小します。
```CSS:CSS
.button:active {
  transform: scale(0.9);
  }
```
これで、`transform`プロパティを使い、インタラクティブなボタンが完成しました。
ユーザーがボタンにマウスオーバーすると少し拡大し、
クリックすると少し縮小する効果があります。

## 参考

https://developer.mozilla.org/ja/



# おわりに
CSSの`transform`プロパティの基本から応用までを紹介させていただきました。
私自身もウェブデザインスキルの向上を目指していきたいと思います。
最後まで読んでいただきありがとうございました。
Azure Administrator Associate(AZ-104)更新体験談

昨年取得したAzure Administrator Associate(AZ-104)の更新期限が迫ってきたので更新しました。今回が初めての更新ということもあり、備忘も兼ねて記録していきます。

![pass.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332975/5c400d1d-c264-eb9e-45f5-8d1b3f528f0e.png)

## Microsoftの資格期限について
Microsoftの認定資格は基礎的な「Fundamentals」に分類される資格を除き、合格日から1年で有効期限が切れてしまうため、継続して資格を保持するためには更新を行う必要があります。

#### Microsoft認定資格更新期限
- Fundamentals・・・無期限
- Role-Based、Specialty・・・合格日から1年間

#### 各資格ごとの分類についてはこちらから
https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE2PjDI

#### 試験概要
- 26問の選択式問題(問題数は多少前後あるかもです)
- 不合格だった場合は24時間後に再受験が可能
- 60%前後で合格

## 更新の流れ

### 1.資格期限が切れる半年前にメールが届く
対象の資格試験の期限が切れる6か月前にメールにて通知が届きます。

![mail.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332975/9a735b76-55fd-b71e-d9d1-17b0f0f9c616.jpeg)

### 2.メールに記載のURLからオンラインで試験を受験
受信したメールに記載のURLから受けられるオンラインでの試験に合格することで資格の有効期限を1年間延長することが可能です。

## 勉強方法
メールに記載のURLからMicrosoftが提供している公式の学習ドキュメントを使うことができます。資格取得後または前回更新時から新しくなった機能やサービスを重点的に学習させてくれるため、一通り目を通すと良いと思います。

## その他体験談

私は3回目の受験で合格しましたが、問題は毎回変わっていてほぼ毎回初見の問題でした。

ipadのブラウザで受験したんですが、3回目の受験を25問ほど解き終えたところで、ブラウザが強制終了してしまい、開きなおしたら1問目から再開になってしまったので、実質4回目での合格です。(泣)

皆様は同じ過ちを繰り返さないよう、電源周りやネットワーク等、受験環境にはお気を付けください...

クラウドサービスの特性上、日に日にサービスが変化していくため短いスパンで更新を行うのは良いと思う反面、保持している資格も増えればめんどくささはありますね！
find_or_create_byメソッドについて

## はじめに

個人開発でOmniAuthを用いた認証機能を実装する際に、```find_or_create_by```メソッドの挙動について疑問が生じたので、その点について調べてみました。

:::note warn

初学者のため間違いがあるかもしれません。
その際はご指摘いただけると嬉しいです。

:::

## 元々の認証機能の一部

既存のユーザーに対して変更があった際には、updateメソッドで更新をしたかったのですが、```user_update(user_params)```の部分が動いていないようだったのでなぜだろうと気になりました。

```ruby
def self.find_or_create_from_auth_hash(auth_hash)
    user_params = user_params_from_auth_hash(auth_hash)
    User.find_or_create_by!(uid: user_params[:uid]) do |user|
     user.update(user_params)
    end
end
```

```ruby:修正後のコード
def self.find_or_create_from_auth_hash(auth_hash)
  user_params = user_params_from_auth_hash(auth_hash)
  if guild_member?(user_params[:uid])
    user = User.find_by(uid: user_params[:uid])
    if user
      user.update(user_params)
    else
      user = User.create!(user_params) do |new_user|
        if new_user.image.nil?
          new_user.image = Discordrb::API::User.default_avatar(auth_hash[:extra][:raw_info][:discriminator])
        end
      end
    end
    return user
  end
  nil
end
```

## 挙動の解説
```find_or_create_by```メソッドは、すでにレコードが存在する場合はそのオブジェクトを返し、存在しない場合は新たにレコードを作成してそのオブジェクトを返します。
見落としていた点としては、```find_or_create_by```メソッドでは、レコードが既に存在する場合はブロック内の処理（この場合は```user.update(user_params)```）を実行しないということです。


## ソースコード


```ruby :activerecord/lib/active_record/relation.rb
def find_or_create_by(attributes, &block)
      find_by(attributes) || create(attributes, &block)
    end
```

### ||の挙動
```
result = a || b
```
このコードでは、aがnilやfalse以外の値であれば、resultにはaの値が代入されます。
aが偽なら、resultにはbの値が代入されます。
つまり、aかbのどちらかが真なら真を返し、両方偽なら偽を返します。

https://pikawaka.com/ruby/logical-operators

## ソースコードの挙動
以下のコードの挙動は下記のようになります。
```ruby
find_by(attributes) || create(attributes, &block)
```
```find_by(attributes)```がレコードを見つけた（```nil```や```false```以外の値を返した）場合は、そのオブジェクトを返し、もし```nil```や```false```になれば後半部のcreateを実行してその結果を戻り値として返します。


上記のコードからわかるように、```find_or_create_by```はまず```find_by```でレコードを検索し、見つからない場合のみ```create```メソッドを呼び出してブロックを実行します。

```ruby :activerecord/lib/active_record/persistence.rb
def create(attributes = nil, &block)
        if attributes.is_a?(Array)
          attributes.collect { |attr| create(attr, &block) }
        else
          object = new(attributes, &block)
          object.save
          object
        end
      end

```

https://railsdoc.com/page/find_or_create_by


## 終わりに

コードが予想と違った動きをするときはソースコードなどをしっかり確認することも大事だということを再確認できました。これからも意識して確認していこうと思います。
PowerApps comboxの保存、表示方法

# 手順

1,DataCardのupdate属性に下記の内容を記載


    ForAll(
    ComboBox1.SelectedItems,
       {
         Id: ID,
         Value: Title
       }
    )

2,ComboxのDefaultSelectedItems 属性に下記の内容を記載

    　ForAll(
       ThisItem.LookUpField,
       {
         Title: Value,
         ID: Id
       }
    　)
# 参考サイト
https://powerusers.microsoft.com/t5/Building-Power-Apps/Combobox-value-is-Not-getting-Saved-in-SharePoint-List/td-p/526271