OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails】バリデーションのスキップ

# はじめに
バリデーションをスキップするメソッドをまとめます。

## update
#### update_all
- 条件に一致するレコードをすべて更新する
- コールバックもスキップする
- updated_at/updated_onは更新されない
```
User.pluck(:code)
=> ["100", "200", "300"]
User.pluck(:updated_at)
=> [Wed, 04 Dec 2024 00:00:00.000000000 JST +09:00, Mon, 16 Dec 2024 10:31:50.000000000 JST +09:00, Sat, 31 May 2025 10:12:59.000000000 JST +09:00]

User.update_all(code: 400)
User.pluck(:code)
=> ["400", "400", "400"]
User.pluck(:updated_at)
=> [Wed, 04 Dec 2024 00:00:00.000000000 JST +09:00, Mon, 16 Dec 2024 10:31:50.000000000 JST +09:00, Sat, 31 May 2025 10:12:59.000000000 JST +09:00]
```
https://railsdoc.com/page/model_update_all
#### update_attribute / update_attribute!
- `update_attribute(属性名, 値)` で更新する
- コールバックはスキップしない
- `updated_at/updated_on`カラムがあれば更新する
```
u = User.first
u.updated_at
=> Wed, 04 Dec 2024 00:00:00.000000000 JST +09:00
u.name
=> "A"

u.update_attribute(:name, "花子")
u.name
=> "花子"

u.updated_at
=> Sat, 31 May 2025 11:11:18.000000000 JST +09:00
```
https://railsdoc.com/page/model_update_attribute

#### update_column / update_columns
- `update_column(属性名, 値)`、`update_columns(属性)` で更新する
- コールバックもスキップする
- `updated_at/updated_on` は更新されない
```
u = User.first
u.updated_at
=> Wed, 04 Dec 2024 00:00:00.000000000 JST +09:00
u.name
=> "A"

u.update_column(:name, "B")
u.name
=> "B"

u.update_columns(name: "C")
u.name
=> "C"

u.updated_at
=> Wed, 04 Dec 2024 00:00:00.000000000 JST +09:00
```

https://railsdoc.com/page/update_columns

https://api.rubyonrails.org/v6.1/classes/ActiveRecord/Persistence.html#method-i-update_columns

## その他

#### increment! / decrement!
- カウントアップ / カウントダウン
```
e = Event.first
e.day  
=> 5

e.increment!(:day, 2)
e.day
=> 7

e.decrement!(:day, 3)
e.day
=> 4
```
https://railsdoc.com/page/increment

#### toggle!
- 属性の反対のブール値を割り当てる
```
u.deleted
=> false

u.toggle!(:deleted)
u.deleted
=> true
```
https://railsdoc.com/page/toggle

#### touch
- `update_at` カラム を現在の時刻に更新する
- 時刻を引数で指定すると、指定した時刻に更新できる
```
u = User.first
u.updated_at
=> Wed, 04 Dec 2024 11:47:50.000000000 JST +09:00

u.touch
u.updated_at
=> Sat, 31 May 2025 10:26:20.000000000 JST +09:00

u.touch(time: Time.new(2025,5,1,0,0,0))
u.updated_at
=> Thu, 01 May 2025 00:00:00.000000000 JST +09:00
```
https://railsdoc.com/page/touch



#### save(validate: false)
- オブジェクトを保存する
```
u = User.first
u.code
=> "100"
u.updated_at
=> Wed, 04 Dec 2024 00:00:00.000000000 JST +09:00

u.code = "200"
u.save(validate: false)
User.first.code
=> "200"

u.updated_at
=> Sat, 31 May 2025 11:28:44.000000000 JST +09:00
```

# おわりに
有効無効に関わらずオブジェクトが保存されてしまうので、使用の際は十分に注意する必要があります。
G検定に合格したけど…これ、役に立つの？

# G検定、合格しました（勉強時間5時間・ノーAIカンニング）
![スクリーンショット 2025-06-09 183450.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043133/80b8ee56-ee78-4e4e-b95b-439fda3ddbbf.png)



G検定に合格しました。  
なお、**チートシートの公開は一切いたしません**。  
それを目的に来た方は、どうか他の記事をご覧ください。

---

## ■ 勉強時間・方法

- 勉強時間：約5時間  （出題方法の確認のみ）
- チートシート：なし  
- AI（ChatGPTなど）を使ったカンニング：なし  
- 使用教材：某アプリ1つ（有料）

![Screenshot_20250531-125313.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043133/6538f6db-df5d-4e02-83c1-4c159f052caa.png)
---

## ■ なぜ受けたのか？

AIという言葉が珍しくもない時代になりましたが、  
平気で誤情報を垂れ流す人があまりに多く、  
**「私はそうなりたくない」**という危機感が出発点です。

そして、私は独自の構築論を展開しており、周囲とまったく話が合いません。  
にもかかわらず、自分の活動では着実に成果が出ている。  
――では、自分の考えはおかしいのか？

その検証手段を探す中で、**「知名度のある資格」**としてG検定を受けるに至りました。

---

## ■ 受験直前とTOEICの既視感

試験前に「2時間160問」と聞き、TOEICの苦い記憶がよみがえりました。  
あの形式がとにかく苦手なので、「やめとけばよかったかな……」とも思いました。  
ただ、いざ受けてみると長文はなく、**1時間以上時間が余りました**。

---

## ■ 試験当日の印象

- 問題の細かさが異常（例：1970年代のAI知識）
- 実務で使わないような知識が多い
- アプリに出てこなかった問題も多数

そこで余った時間を使い、ChatGPTにスクリーンショットを送って  
「このAIで解かせたら合格できるか？」を検証しました。

![スクリーンショット 2025-05-10 165704.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4043133/53ee1429-3489-484d-9f2c-3ebc25e73dd8.png)

正答率はおおよそ50%。  
今後のOCRや画像認識精度の向上を考えれば、  
**「AIだけで合格」は時間の問題**と感じました。

---

## ■ 資格の価値についての所感

私の目的や基準からすると、この資格にはやや乖離を感じました。

- トリビア問題が多く、実務に使える知識は少ない
- トランスフォーマーの仕組みや実装に触れた問題は皆無
- 深層学習以降の技術だけで十分では？

参考書も乱立しており、**「知識詰め込み型の限界」**を感じました。

---

## ■ 資格とAI活用の未来

最近「プロンプトエンジニアリング」のような新資格も出ていますが、  
プロンプトはあくまで**“引き出す技術”**。  
本質はモデルやデータの設計にあります。

AIを本当に使いこなす知見よりも、表面的な権威だけで収益化を目指す姿勢には懸念を覚えます。
そうした構造が結果として、日本のAI活用の遅れに繋がってしまうのではないか──と危機感を持っています。

---

## ■ 結論：試験制度は限界に近い

AI技術が進化すれば、「資格突破支援エージェント」が実用化される未来も考えられます。
実際にそういった仕組みを模索してみたくなる自分もいます。

<!-- 合格発表のスクリーンショットをここに挿入 -->

---

## おわりに

この資格を通じて、  
**「AIは誰のために、何を目的に学ぶべきか？」**を考える機会になりました。

私は、資格を取って満足するよりも、  
**“結果につながる構築論”**を展開する人のほうが、  
AIにふさわしいと感じています。

そう思ったのは、上司に報告したときに言われた言葉ですね。
「資格よりも、有形の成果を見せてほしい」

ホント、その通りだと思いました。

---
【React】useStateで配列を更新してもすぐにlengthが合わない理由と対処法

# 問題
useStateで管理している配列で、更新したにも関わらず配列の数が合わない。

```React.js
const [messages, setMessages] = useState<string[]>([]);

// 中略
    await setMessages((prevMessages) => [...prevMessages, input]);

    console.log("messages.length", updatedMessages.length);
```

実際の出力：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3881019/7cad2448-4ad4-40b7-973b-218a6d6d8d62.png)

# 原因
useStateの特性として以下がある。
- setState（今回の例では setMessages）は 非同期的に状態を更新する
- ただし、Promise を返さない → await しても待てない
- 状態は「次のレンダー」で更新される

# 解決方法
状態を即時に使いたい場合は、useStateで更新されるmessagesの代わりに、更新済みのローカル配列を使う。


```React.js
const [messages, setMessages] = useState<string[]>([]);

// 中略
// updatedMessagesを定義
    const updatedMessages = [...messages, input];
    setMessages(updatedMessages);

//その数をカウントする
    console.log("messages.length", messages.length);
```

実際の出力：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3881019/ff839a4c-723a-4a9b-9c90-e09eb3b7a4f7.png)

# 終わりに
最初はawaitすれば状態も更新されると思っていたので、思わぬはまりポイントでした。
同じように「なぜlengthが合わないの？」と悩んでいる方の助けになればうれしいです.
Slack Compose Lintの簡単なセットアップを説明した

# はじめに
どうも、ikasumi1503です。[Kotlinのリンターシリーズ](https://qiita.com/ikasumi1503/items/5c4ae78a64b7a8d40ffe)のSlack Compose Lint編です。JetpackComposeプロジェクトでリンター設定をしていきたい場面は多いかと思います。そこで、本記事ではSlack社が提供しているCompose Lintの簡単な設定方法をまとめていこうと思います。

# 導入方法
導入方法を次の順で紹介していこうかと思います。

1. Slack Compose Lintを手動＆自動で実行する
2. Github actions連携

### 1. Slack Compose Lintを手動＆自動で実行する

プロジェクトのbuild.gradle.ktsを開きましょう。見つからないという方はshiftキーを2回押してなんでも検索によってこのファイルを見つけ出しましょう。
```
// プロジェクト構成：
your-project/
├─ build.gradle.kts        ← × 
├─ settings.gradle.kts
├─ app/
│  └─ build.gradle.kts       ← 〇ここです
```

見つけたら、早速プラグインを入れます。

``build.gradle.kts``
```
dependencies {
    lintChecks("com.slack.lint.compose:compose-lint-checks:1.4.2")
}
```
これで右上に出ている**Sync now**をクリックすると、設定が適用されます。以上でセットアップは完了です。簡単ですね。ルートディレクトリで``./gradlew lint``コマンドを実行して無事警告が表示されたら設定は完了です。

### 2. Github actions連携

PR時にComposeLintで検知されるとエラー内容をまとめたファイルを作成するようにします。
プロジェクトの``.github/workflows``にymlファイルを入れていきます。
ファイル内容は長いので次のレポジトリ内に入れています。あくまで例としてAIに吐き出させたものを使っています。一応私の環境では動作確認済みです。
https://github.com/ikasumi1503/KtlintSample

``slackCompose_reviewdog_example.yml`` ... 一応reviewdogバージョンも出しておきます。プルリクエストしたら警告内容をPRコメントにばらまきます。
以上のファイルがmainブランチにないと機能しない点にご注意ください。

# さいごに
以上がSlack Compose Lintの簡単な設定方法です。ぜひ試してみてください。
【Go】手軽にCLIツールを作成できるCobraを触ってみた


## 概要

- Go製のCLIツールを簡単に開発できるフレームワーク[Cobra](https://github.com/spf13/cobra)を触ってみた
- インストール方法や簡単なサンプルコード

## インストール、動作確認

1. cobraをインストール

```shell
$ go get -u github.com/spf13/cobra@latest
```

1. cobra-cliをインストール

```shell
$ go install github.com/spf13/cobra-cli@latest
```

1. テンプレート作成

```shell
cobra-cli init --license MIT --viper=false
```


下記のようなテンプレートが作成される


```shell
├── cmd
│   └── root.go
├── go.mod
├── go.sum
├── LICENSE
├── main.go
```

1. 動作確認

```shell
$ go run main.go
A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
```


## コマンドを追加してみる


例えば「hello」というコマンドを作りたい場合は、


```shell
cobra-cli add hello
```


`cmd/hello.go` が自動生成される


```go
/*
Copyright © 2025 NAME HERE <EMAIL ADDRESS>

*/
package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// helloCmd represents the hello command
var helloCmd = &cobra.Command{
	Use:   "hello",
	Short: "A brief description of your command",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("hello called")
	},
}

func init() {
	rootCmd.AddCommand(helloCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// helloCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// helloCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
```


実行してみる


```shell
$ go run main.go hello
hello called
```


## フラグの追加


```go
package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)


var name string

// helloCmd represents the hello command
var helloCmd = &cobra.Command{
	Use:   "hello",
	Short: "挨拶を表示するコマンド",
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Printf("Hello, %s!\n", name)
	},
}

func init() {
	rootCmd.AddCommand(helloCmd)
	
	// フラグ追加
	helloCmd.Flags().StringVarP(&name, "name", "n", "World", "名前を指定できます")
}
```


実行してみる


```shell
$ go run main.go hello
# => Hello, World!

$ go run main.go hello --name Taro
# => Hello, Taro!

$ go run main.go hello -n Jiro
# => Hello, Jiro!

```


## まとめ

- インストールから実行まで非常に手軽だった
- まだ作りたいCLI思い浮かばないが、機会があれば使っていきたい
Amazon Q CLIでゲームを作ってみた

こんにちはnagisa_53です。

以下のキャンペーンが話題になっていたので、Amazon Q CLIを使ったゲーム作りに挑戦してみました。

https://aws.amazon.com/jp/blogs/news/build-games-with-amazon-q-cli-and-score-a-t-shirt/

## 前提環境

Windows勢（Windows11）のため、WSL2のUbuntu（24.04.1 LTS）にAmazon Q CLI（q 1.10.2）を導入しています。

## やってみる

キャンペーン用のページで、ゲーム用のライブラリとして[PyGame](https://www.pygame.org/wiki/GettingStarted)が紹介されていたので、特に使用ライブラリにこだわりがなかったので、以下のDebian/Ubuntu/Mintの手順に従いPyGameを導入しました。（Python3は事前に導入済）

https://www.pygame.org/wiki/GettingStarted

これで事前セットアップは完了したので、ここからAmazon Q CLIと会話しながらゲームを作っていきます。

特にこれといったアイディアはなかったので、まず以下のインプットからアイディア出しも手伝ってもらいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/47ba3ede-c93f-452f-9c30-35755ff918c9.png)

すると、以下のような案を出してくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/86ef0e49-1473-4137-8629-2856d349ec5c.png)

今回は2をベースにゲームを作ることにしました。
（正確に言うとこの時点では1+2の案でゲームを作るつもりだったのですが、複雑性やバグの問題から最終的には2ベースのゲームに落ち着きました。）

コード作成や実行方法の提示を依頼すると、以下のようにコードの生成や実行方法、ゲームの遊び方までを提示してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/540de02b-2616-44c4-9a27-a1ec61115d0e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/dda78a3a-dcd9-4ffd-9331-3972b6a037d0.png)

実際作成されたコードを元にゲームを実行してみると
- （文字を探すゲームのはずが）文字がランダムに抽出されてしまい単語ができない
- 選択したブロックが分かりづらい
- 一度選択すると解除できない
- 文字同志が重なるなど表示の問題がいくつか

と、いくつか不具合があり、そのあたりはAmazon Qと会話しながら修正していきました。

また、機能として
- 探索する単語の長さを自由に選べる
- 探索する単語数を自由に選べる

なども会話しながら追加しており、ゲーム完成までにAmazon Qとは合計20回程度やり取りを行っています。

やり取りの例：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/e173cae1-04ee-4440-b608-d4c49b3f1fba.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/b0d3f509-c8cd-47aa-8168-58d02bdcfd09.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/36679f22-87cf-48e6-8865-17cf5d897898.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/54f57bfd-a4f9-4e77-b642-08a333aecb36.png)

## やってみる

そして完成したゲームが以下です。

### 設定画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/e903304d-027d-495c-bf7f-b79c11b10a35.png)

設定画面で、文字数の最大/最少と、探す単語数を設定します。

### ゲーム画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/5d6defc6-9151-4b23-ad86-18b60b63fa1f.png)

制限時間5分の中で、探索対象の単語を見つけてブロックを選択します。
見つかるとポイントが入ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/371b4553-c433-4031-9407-a32661ac671b.png)

↑は選択中

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273915/4f56fd67-1203-46bc-8da3-109545dcba8d.png)

↑は単語が見つかってポイントが入ったところ

<br>
だいぶ改善の余地はありそうですが、一応遊べるゲームになっています！

ソースコードは一応以下で公開しています。
（必要ファイル類も一式Amazon Q CLIが作ってくれました！）

https://github.com/nagisa53/nagisa_amazonq_game

## まとめ

普段アプリケーションコードは書かないインフラ屋さんですが、Amazon Q CLIと1～2時間会話するだけでゲームを作ることができました！

生成AIを利用することでこれまで手を出しづらかった領域に手を出しやすくなったなと感じます。どう使えるのかや、本質的な発想力が今まで以上に求められますね。

せっかくなので作ったゲームは改良していきたいと思います。
AWSのS3とCloudFrontでブログ作ったときに詰まった箇所まとめました

# はじめに

S3 + CloudFront + Route 53 + Next.jsでブログを作ったのですが、
作っている途中で詰まったことをまとめました。

## Next.js関連

・App routerではnpm run exportが不要らしい。ChatGPTがやたらとこのコマンドを進めてきて混乱した。頑張って実行しようとしたのに……

・リンクで日本語を扱う場合はエンコードが必要。404エラーで焦るぞ。

・mdxで作った記事ページの改行コードをいちいちLFにしないとビルド通らないのが地味にめんどくさい。

・Next.js のバージョンによりLinkタグの中に直接文字列を書くとエラーになるっぽい。

## SEO関連

・内部リンクするときは末尾に/を付けないとgoogle search consoleのインデックス登録で重複ページ扱いになる。ブラウザで確認すると、/なしのページに飛ぼうとすると勝手に/ありのページにリダイレクトされてた。（なんで？）

・タグページとか、記事一覧のページは頻繁に更新されるため、これをインデックス登録されると、検索で出た説明とちょっと違う内容のページを出すことになって検索から入ってきた人が混乱する。そのためタグページとか、記事一覧のページはインデックス登録されないように

  `<meta name="robots" content="noindex, follow">`

をつけると無難な気がする。ｼﾗﾝｹﾄﾞ

・サブドメインwwwありのURLからサブドメイン無しのURLにリダイレクトしたほうがSEO的にはいいらしい。ただAWSの設定がめっちゃめんどくさかった。（何がめんどくさかったかは忘れました。許してちょんまげ）

## AWS関連

・将来的にドメインを取得する場合、S3のバケット名はドメイン名と同じにしておく。あんまり考えてなくて作り直してめんどくさかった。

・ap-northeast-3（大阪）で最初S3の静的ホスティングでブログを立ち上げようとしたが、大阪のサーバーはバックアップとか特殊な用途向けのサーバーらしく、ここでブログを作ろうとしたのに機能制限されてて、結局ap-northeast-1に移す羽目になった。

・Certificate Managerで証明書を発行するときにRoute 53でレコードを作成をやっておかないと「保留中の検証」からずっと変わらない。処理してんのかな？と思って一日放置しても変わってなくて悩んだ。

・Certificate Managerで証明書を取得するときに、us-east-1（米国バージニア北部）を選んで取得しないと、CloudFrontでカスタム証明書を設定しようとしたときに選択できなくて焦る。罠やん

・CloudFrontのキャッシュを削除しないと、サーバーに変更したコードをあげてもすぐに反映されない。

・Google search consoleで設定するTXTレコードはRoute 53で登録しないといけないらしい。最初お名前ドットコムで設定してたらいつまでも設定完了せず悩んだ。

・お名前ドットコムでDNS設定してたらダークパターンのGUIで勝手に有料オプション課金されて憤慨！すぐさまお問い合わせしてごねたら返金してもらえた。

# まとめ

色々と詰まったことはありましたが、
AWSは安くて助かるし、
WordPressで作るよりも自作したほうがカスタマイズ性あって個人的には楽しかったです。

作ったブログはこちらになります。
https://bamba-news.com/
docker-compose.ymlの変数展開 "docker cocmpose convert"コマンド

## 導入

私は新卒でエンジニアをやっております。

まずはこの記事を読んでくれて、ありがとうございます。

自分は少し前に、気になっていたことがあります。

**「docker-compose.ymlで呼んでいる変数には、実際にどういう値が入っているのだろう」**
ということについてです。

これが分からないとデバッグのしようがありません。

プログラミングでも、
- ログを確認する
- 変数に格納された値を出力してみる
- データ型を確認してみる

こういったやり方で修正しようとしますよね

Dockerでもエラーが起きた際に、知りたいなと思い、方法を調べました。

それを本記事でお伝えする次第です！

## docker compose convertコマンド

結論、こちらのコマンドで出力できます
```
docker compose convert
```

試しに、以下のようなdocker-compose.ymlファイルがあるとします。
```
version: '3.8'

services:
  db:
    image: postgres:latest
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - postgres_volume:/var/lib/postgresql/data
      - ./docker/postgres/script:/docker-entrypoint-initdb.d
      - ./docker/postgres/postgresql.conf:/etc/postgresql/postgresql.conf
    ports:
      - '5432:5432'
    networks:
      - app-networks
    env_file:
      - ./docker-setting/.env
```
ここで、用いられている変数は以下のところです。
```
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
```
これらは.envファイルから読み込みます。

:::note warn
docker-compose.ymlから読み込む.envファイルは、デフォルトで同階層上にあるファイルを参照します。
上の例では、.envファイルが同階層上にはないため、"env_file:"で相対パスを指定しています。
:::

試しに、この部分でエラーが出たとしましょう
「実際にはどんな値が入っているんだろう」と

では`docker compose convert`を入力してみましょう。
すると、コマンド上でこんな出力を得られます。

![スクリーンショット 2025-05-31 12.04.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3566879/2e87c1a6-f624-4a4b-81f6-173cb3e35b84.png)

先ほど、変数を呼び出していたところみて見てください。
こちらは筆者が適当に.envで宣言した値です。

※筆者はガンダムファンであるため、newtypeと入っています。

これで確認できました！

## 終わり
ちなみにこちらは以下の公式ドキュメントにあります。
ぜひこちらも確認してみてください。

https://docs.docker.jp/engine/reference/commandline/compose_convert.html
【rails】Rails 8のallow_browser modernによる開発者モードでのエラーの解決方法


## はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
rails8 を使用して Rails アプリを作成しているのですが、開発者モードで UI を確認していたらエラーが発生しました。
どうやら、`application_controller.rb`にデフォルトに作成される`allow_browser versions: :modern`が原因でした。
本日は推測される原因や解決策について記事にしようと思います。

---

### `allow_browser versions: :modern`の意味

`allow_browser` は Rails 8 で追加された新しい DSL(Domain-Specific Language：ドメイン固有言語) で、指定したブラウザーのバージョン以下のアクセスを拒否するための機能です。
なお、`allow_browser versions: :modern` は Chrome, Safari, Firefox などの最新バージョンを指し、それ以外の古いブラウザを拒否

```ruby
class ApplicationController < ActionController::Base
  allow_browser versions: :modern
end
```

---

### 開発者モードでエラーが起こる原因

Chrome などのブラウザで **開発者モードを有効にしていると、ブラウザの User-Agent が特殊なものとなり、Rails 側でモダンブラウザとして認識されない場合があります**。

そのため development 環境でも `allow_browser` を設定すると、開発者モードからのアクセスで拒否され、エラーになります。

---

### 解決策

私は以下のように「**本番環境のみ**」適用するよう修正しました：

```ruby
class ApplicationController < ActionController::Base
  if Rails.env.production?
    allow_browser versions: :modern
  end
end
```

この設定により、**development や test ではエラーが発生せず**、本番環境でのセキュリティ強化だけを実現できます。

---

### 結論

| 項目   | 内容                                                                        |
| ------ | --------------------------------------------------------------------------- |
| 意味   | `allow_browser versions: :modern` は古いブラウザを拒否する Rails 8 の新機能 |
| 原因   | 開発者モードの Chrome などで User-Agent が特殊になり拒否される              |
| 解決策 | `if Rails.env.production?` で本番のみ適用する                               |
無料で使える！VSCode × Gemini Code Assistの導入

# はじめに
GoogleのAIコーディングアシスタント「Gemini Code Assist」（旧Duet AI）は、Visual Studio Code（VSCode）で使える無料のAIコーディングアシスタントです。
VSCodeでAIを気軽に無料体験したい初心者、エンジニア、学習者におすすめです。
日本語で質問や指示することも可能です。

# Gemini Code Assist とは
Gemini Code Assistは、Googleが開発したAIコーディングアシスタントです。
以前は「Duet AI for Developers」として提供されていましたが、その後「Gemini Code Assist」としてリブランドされました。
主な特徴は以下のとおりです

### 主な機能
- **コード補完**：AIが次のコードや関数を提案
- **自然言語でのコード生成**：「〇〇のコードを書いて」と指示できる
- **エラーやコードの解説**：質問すると内容や問題点を説明
- **多くの言語に対応**：Python・JavaScriptなど幅広くサポート

### 個人ユーザの利用は基本無料！
2025年5月現在、Gemini Code Assistは個人ユーザ向けに主な機能を無料で提供しています。
コード補完、自然言語によるコード生成、エラー・解説機能など基本的なAIアシスト機能は全て無料で利用可能です。


# 事前準備
- **Googleアカウント**：Googleアカウントが必要
- **VSCodeのインストール**：VSCodeがダウンロード＆インストールされている

# VSCodeにGemini Code Assist拡張機能を追加する手順
### 1. VSCodeを起動

### 2. 拡張機能パネルを開く
左サイドバーの「拡張機能」アイコン（四角いマーク）をクリック

### 3. 「Gemini Code Assist」を検索
検索ボックスに「Gemini Code Assist」と入力

### 4. 拡張機能を選択してインストール
検索結果から「Gemini Code Assist」をクリックし、「インストール」ボタンをクリック

![7c998b3634580a239d3c-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4001795/84946166-c43b-4792-b07b-3c3a9e342336.png)
※すでにインストールしている状態です

### 5. Googleアカウントでサインイン
インストールが完了したら、Googleアカウントでログイン・認証を行います

#### 5-1. 拡張機能のサイドバーを開く
インストールが完了すると、画面左のサイドバーまたは画面右下に「Gemini Code Assist」拡張の通知やアイコンが表示されます

#### 5-2. 「Sign In」または「Googleでログイン」ボタンをクリック
Gemini Code Assistのウィジェットや通知、拡張機能パネル上に「Sign in」あるいは「Googleでログイン」というボタンが表示されるのでクリック

#### 5-3. ブラウザが自動で開く
ボタンをクリックすると既定のウェブブラウザが自動で立ち上がり、Googleログインページに遷移します

#### 5-4. Googleアカウント情報を入力
Googleアカウントのメールアドレスとパスワードを入力し、「次へ」と進む

#### 5-5. アクセス権限の確認と許可
Gemini Code AssistがGoogleアカウントへのアクセス権限を求めてくるので、内容を確認し「許可」または「同意する」をクリック

#### 5-6. 認証完了のメッセージを確認
「認証が完了しました」などのメッセージが表示されるので、ブラウザを閉じVSCodeの拡張機能パネルに戻る

#### 5-7. サインイン済みを確認
VSCodeの拡張機能パネルかウィジェット上で、Googleアカウント名が表示されていることを確認する

### 6. 準備完了
これで導入は完了です。エディタ内でGemini Code Assistの提案や回答が使えるようなります

![7c998b3634580a239d3c-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4001795/391d4df8-ffa3-4025-b832-22c0ab16a248.png)

# 指示してみる
"pythonで1から100までを加算するプログラムを書いて"と指示してみる

![7c998b3634580a239d3c-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4001795/f520dbe4-fe59-424d-a83b-0380c80fd773.png)


# まとめ
Gemini Code AssistはGoogleが提供する無料のAIコーディングアシスタントで、VSCodeにも簡単に導入できます。
VSCodeの拡張機能からインストールし、Googleアカウントでサインインするだけで、すぐに利用を開始できます。
誰でも短時間でAIによるコード補完や解説を体験できます。
まずは気軽に導入して、最新のAIサポートを試してみましょう！
Obsidianの小技その15｜コマンドパレットをピン留め★で快適化

![bbf2020f-502f-408f-926b-fbd02963254c_opt.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/abc4f415-7151-4669-b7b7-750fb25968fc.jpeg)


## はじめに｜Obsidianをもっと自分仕様に

全世界のObsidianユーザーの皆さん、こんにちは！

Obsidianには ⌘/Ctrl + P で呼び出せる **コマンドパレット** が備わっています。  
ふつうに選ぶだけでも便利ですが、**よく使うコマンドを「ピン留め」** しておくと、次のようなメリットがあります。

- 一発で呼び出せるので、検索やショートカット入力が不要
- 自分の作業フローが可視化され、再現性が上がる
- “いま本当に使っている操作”を整理できる

:::note
キーボードから手を離さなくていいのが最高です
:::

本記事では **ピン留めの方法** と **筆者が実際に固定している 5 コマンド** をご紹介します。

## 設定方法｜ピン留め★はどこで？

### ステップ1｜設定からピン留め

![SS 2025-05-31 10.55.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/dc2ed33b-55d7-4d57-a575-129b17b8bfcf.png)

1. 設定画面を開く
2. コアプラグイン > コマンドパレットを選択
3. コマンドの新規ピン留めに入力

:::note
並び替えはドラッグ＆ドロップで自由に変更できます。
:::

### ステップ2｜⌘/Ctrl + P で呼び出し

![SS 2025-05-31 10.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184128/d986d530-7090-4907-94d7-ee34a7b7ac2d.png)

これで、コマンドパレット（ ⌘/Ctrl + P）から、よく使うコマンドをすぐに使えます。


## 実例｜私のピン留め5選

- テンプレート: テンプレートを挿入
  ⇒ コアプラグインのテンプレートを選択します。頻度高く使います
- PDFにエクスポート
  ⇒ 他人に資料を渡すときに頻度高く使用。頻度高く使います
- Pandoc Plugin: Export as Mord Document (docx)
  ⇒ Wordで渡す必要があるときに。頻度は低いけど重要
- ブロッククォートをトグル
  ⇒ショートカットキーをすぐ忘れるので
- すべての見出しとリストをフォールド
  ⇒たまにしか使わないけど、使うときには迷いたくない

:::note
めちゃくちゃよく使うものか、たまに使うけれど、迷子になりがちなものをピン留めしています。
:::


### コツ｜少数精鋭で快適キープ

- **最初は 2〜3 個だけ** ピン留めして、次第に増やしていくのがオススメ
- 使わなくなったらピン留めを外して整理（“今の自分” に合わせる）  
- Obsidian Copilotのカスタムコマンドとも相性がいい

## おわりに｜“作業導線”をつくる小技

ピン留めは **0 分で導入できる小さな効率化**。
よく使う操作をすぐ呼べるようにしておくと、Obsidianの“作業導線”が快適になります。

**コマンドパレットをピン留め★で快適化**、ぜひ試してみてください。

### 参考リンク

- [Obsidian｜使いかたとコツ（目次）](https://qiita.com/hann-solo/items/ac8fa75394813e8adcf4)

### 環境

- Obsidian v1.9.1
- macOS Sequoia 15.4.1
- MacBook Pro (14-inch, 2021)
Windowsで良く使う便利な操作

# 二つの画面を左右にきれいに並べたい
```
Windowsキー＋→か←
```
or
```
画面の右端か左端へウィンドウをドラッグ
```

# スクショ撮りたい
```
Windowsキー＋Prtsc
```

# 画面一部のスクショ撮りたい
```
Windowsキー＋Shift＋S
```
or
```
Windowsキー→「sn」でエンター、SnippingTool起動
```

# 操作を記録しておきたい、手順書にしたい
```
Windowsキー＋R　→　psr
```

# タスクマネージャ起動したい
```
Ctrl＋Shift＋Esc
```

# エクスプローラでファイルやフォルダのプロパティを開きたい
```
Alt＋Enter
```

# エクスプローラとか開きすぎてどこいった状態
```
タスクバーのアイコンを、Ctrl押しながらクリック連打
```

# エクスプローラとか閉じたい
```
Alt→スペース→C　＃最近chatGPTアプリの起動ショートカット「Alt＋スペース」と競合気味で困ってる
```
or
```
Alt＋F4
```

# エクスプローラとか新しいプロセスで開きたい
```
タスクバーのアイコンを、Shift押しながらクリック
```

# エクスプローラでファイルやフォルダをコピーしたい
```
Ctrl押しながらドラッグアンドドロップ
```

# エクスプローラでファイルやフォルダのショートカットリンクを作りたい
```
Ctrl＋Shift押しながらドラッグアンドドロップ
```
or
```
Ctrl＋C　→　右クリック→S
```

# win10でカレンダー表示したい
```
Windowsキー＋Alt＋D
```

# win11のエクスプローラで以前の右クリックメニューを見たい
```
Shift押しながら右クリック　＃この改変は個人的には面倒なのでやめてほしかった
```
プロデル、調査 その14

# 概要
プロデルが、CLRらしいので、調べて見た。
練習問題やってみた。

# 練習問題
sqliteで、CRUDせよ。

# テーブルを作成する

```
SQLiteというSQLiteデータベースを作る
SQLiteのデータソースは「database.db」
SQLiteへ接続する
SQLiteで「CREATE TABLE 楽曲 (曲目番号 INTEGER PRIMARY KEY AUTOINCREMENT, 曲名 TEXT, アーティスト TEXT, アルバムID INTEGER);」を実行する
SQLiteから切断する

```


# create

```
SQLiteというSQLiteデータベースを作る
SQLiteのデータソースは「database.db」
SQLiteへ接続する
「INSERT INTO 楽曲 (曲名,アーティスト) VALUES ('I AM YOUR SINGER','サザンオールスターズ')」をSQLiteで実行して、結果とする
「［結果］件、処理しました」を情報アイコンで表示する
SQLiteから切断する

```

# read

```
SQLiteというSQLiteデータベースを作る
SQLiteのデータソースは「database.db」
SQLiteへ接続する
SQLiteから「SELECT 曲名 FROM 楽曲」を取得して、結果とする
結果の内容を情報アイコンで表示する
SQLiteから切断する

```

# update

```
SQLiteというSQLiteデータベースを作る
SQLiteのデータソースは「database.db」
SQLiteへ接続する
「UPDATE 楽曲 SET 曲名='I am your singer' WHERE 曲名='I AM YOUR SINGER'」をSQLiteで実行して、結果とする
「［結果］件、処理しました」を情報アイコンで表示する
SQLiteから「SELECT 曲名 FROM 楽曲」を取得して、結果とする
「更新後」として結果の内容を情報アイコンで表示する
SQLiteから切断する

```

# delete

```
SQLiteというSQLiteデータベースを作る
SQLiteのデータソースは「database.db」
SQLiteへ接続する
「DELETE FROM 楽曲 WHERE 曲名='I AM YOUR SINGER'」をSQLiteで実行して、結果とする
「［結果］件、処理しました」を情報アイコンで表示する
SQLiteから切断する

```

以上。
lambda+Gatewayを利用してAPIへアクセスする方法

# 背景
React Native (Expo) アプリで OpenAI API を使って英語フラッシュカードを自動生成するアプリを開発しています。  

当初は OpenAI API に直接リクエストを送っていましたが、現在は以下のような構成に移行しました。

現在は「Expo→API Gateway→Lambda→OpenAI」という構成に移行しました。

https://qiita.com/JZ8xNeXY/items/79a09002f5e7ea658604

# メリット
| 項目       | 説明                             |
| -------- | ------------------------------ |
| セキュリティ向上 | APIキーをクライアント側に埋め込まない           |
| 不正利用防止   | コード分析やネットワーク監視でもAPIキーが見られない    |
| 利用量管理    | 誰がどれだけ使ったかを追跡可                 |
| ロジック加工   | 入力値検証やログ出力も可能                  |

# 当初の構成
```request.js
// アプリ側
const API_KEY = *************************
const response = await axios.post('https://api.openai.com/v1/chat/completions', {
  model: 'gpt-4o-mini',
  messages: [...],
}, {
  headers: {
    Authorization: `Bearer ${API_KEY}`
  }
})
```

## 問題点
- アプリにAPIキーが埋め込まれる
- ビルド時にAPIキーがコード内に埋め込まれ、添付JSから取得可能
- 不正利用されると請求額が増える恐れ


# 改善後
![Screenshot 0007-05-31 at 11.07.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/917693/b71a5fd4-5332-47fe-b99c-0d9692f6d7a7.png)

Expoアプリから lambdaへのリクエスト

```request.js
const API_URL = ****************
const API_KEY = ****************

const response = await axios.post(API_URL, { prompt }, {
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': API_KEY,
  },
})
```

lambdaのコード
```index.mjs
export const handler = async (event) => {
  const body = JSON.parse(event.body || '{}')
  const prompt = body.prompt || 'default'

  const response = await fetch('https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'gpt-4o-mini',
      messages: [...],
    })
  })

  const data = await response.json()
  return {
    statusCode: 200,
    body: *************** })
  }
}
```

# まとめ
ExpoでOpenAI APIを利用する際は、「API Gateway + Lambda」でキーを隠蔽しながら、ロジックを分離して実装しました。

# おまけ
おまけ：なぜ .env や eas.json で隠しても完全ではない？

Expoのビルドプロセスで .env や eas.json にキーを定義しても、最終的にはバンドルされたJSコードに「値」が入るため、秘匿にはなりません。
重要なAPIキーは必ずサーバーサイド（Lambdaなど）で保持しましょう。
ubuntuでの日本語設定

linux初心者がubuntuをwindowsライクに日本語入力ができるようにしたことの備忘録を残します。
# 動作環境
Ubuntu 24.04
# Fcitx(ファイティクス)のインストール
Fcitxとは、多数の言語を管理するためのフレームワークです。
Fcitx上でMozcなどを管理します。

まずはFcitxのインストールです。
~~~
sudo apt install fcitx5-mozc
~~~

# Fcitx5の設定
インストールが終了したら、App showsより「Fcitx５ 設定」を起動。
![Screenshot from 2025-05-31 10-06-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2673445/6c8a4b55-1a3c-4596-8cac-7123ec3639a8.png)

デフォルトでは、「キーボード-英語(US)」となっているので、これを上記写真のように変更してください。
このキーボードは、日本語キーボードでアルファベットと半角記号を入力するためのキーボードの選択です。
他のキーボードでも良いですが、現在一般的に使われている日本語キーボードの配列とは少し異なります。

次に、半角全角キーで日本語（Mozc）と英語（キーボード-日本語）の切り替えを行います。
「グローバルオプション」タブから、「入力メソッドの切り替え」を変更します。
デフォルトでは下記のようになっています。
![Screenshot from 2025-05-31 10-43-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2673445/d4b1c8df-5fd3-40ea-a4d4-7a0ca75b4f29.png)

隣の「ー」ボタンで削除、「＋」で追加です。
一番上の「Control+スペース」をクリックすると「..」となり、キーの選択モードに入ります。
この状態で半角全角キーを押し、他のボタンを削除すると、下記写真のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2673445/f8b03f40-9482-4820-830c-7461a461c691.png)
場合によっては、半角全角キーを押すと「❜」と表示されることがあるかもしれませんが、
私の場合はその場合でもうまく行きました。

これでwindowsライクに文字入力ができるかと思います。
Lovableが.envに未対応

Lovableで生成されたSupabase接続アプリでは、接続情報が、
src/integrations/supabase/client.ts
に直接書かれていました。
これは良くないだろうということで、Cursorの支援で生成してもらった修正ソースは下記のような形。

```ts:client.ts
// This file is automatically generated. Do not edit it directly.
import { createClient } from '@supabase/supabase-js';
import type { Database } from './types';

if (!import.meta.env.VITE_PUBLIC_SUPABASE_URL) {
  throw new Error('Missing env.NEXT_PUBLIC_SUPABASE_URL');
}
if (!import.meta.env.VITE_PUBLIC_SUPABASE_ANON_KEY) {
  throw new Error('Missing env.NEXT_PUBLIC_SUPABASE_ANON_KEY');
}

// Import the supabase client like this:
// import { supabase } from "@/integrations/supabase/client";

export const supabase = createClient<Database>(
  import.meta.env.VITE_PUBLIC_SUPABASE_URL,
  import.meta.env.VITE_PUBLIC_SUPABASE_ANON_KEY
);
```

ところが
https://feedback.lovable.dev/ja/p/put-the-supabase-credentials-in-a-env-or-config-file

こちらでもやり取りされているように、Lovableは.envに対応されていないということで、環境変数の設定もできません。
上記でもコメントしている人がいますが、皆さん気にされていないのが不思議・・・

仕方ないので、client.tsに書いておきますが、将来に期待して、.envから読み込める場合はそれを読んで、読み込めない場合は固定値を使おうと思いました。
そこで、それぞれの変数を定義したところ、

```ts:client.ts
//Lovable はまだ.envに対応していないのでやむを得ず
let sburl;
let sbakey;
```

こんな提案をしてくれるCursor。

```ts:client.ts
if (import.meta.env.VITE_PUBLIC_SUPABASE_URL) {
  sburl = import.meta.env.VITE_PUBLIC_SUPABASE_URL;
}else{
  sburl = "https://giji-search-spark.supabase.co";
}
if (import.meta.env.VITE_PUBLIC_SUPABASE_ANON_KEY) {
  sbakey = import.meta.env.VITE_PUBLIC_SUPABASE_ANON_KEY;
}else{
  sbakey = "xxx";
}
```

変数名だけでなんで分かった？？
可愛すぎる・・・

Cursorが本題のようになりましたが、Lovableにはぜひ対応していただきたい。
プロデル、調査 その13

# 概要
プロデルが、CLRらしいので、調べて見た。
練習問題やってみた。

# 練習問題
GUIアプリを、作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/75b0b216-5c43-49be-aff1-18fdb12fa0a2.png)

# サンプルコード

```
メイン画面を表示する
待機する
メイン画面とは
	ウィンドウを継承する
	はじめの手順
		初期化する
		ーー貼り付けた部品に対する操作をここに書きます
	終わり
	初期化する手順
		ーー自動生成された手順です。ここに書き加えたプログラムは消える可能性があります
		初期化開始する
		ボタン3というボタンを作る
		ボタン2というボタンを作る
		ボタン1というボタンを作る
		この実質大きさは{357,328}
		この内容は「ランチャー」
		この移動順は0
		ボタン3を使う
			その位置と大きさは{85,218,93,28}
			その内容は「メモ帳」
			その移動順は2
		ボタン2を使う
			その位置と大きさは{83,141,93,28}
			その内容は「電卓」
			その移動順は1
		ボタン1を使う
			その位置と大きさは{86,59,93,28}
			その内容は「ペイント」
			その移動順は0
		初期化終了する
		この設計スケール比率は{120,120}
	終わり
	ボタン1がクリックされた時の手順
	「mspaint.exe」を、起動する
	終わり
	ボタン2がクリックされた時の手順
	「calc.exe」を、起動する
	終わり
	ボタン3がクリックされた時の手順
	「notepad.exe」を、起動する
	終わり
終わり

```

以上。
Amazon Transcribeで文字起こしを試してみた

# 背景・目的
音源はあったが、スクリプトが手元になく、AWSのTranscribeを使用して作成したときのメモ書きです。

# 概要
## Transcribeの概要

以前、下記に概要をまとめました。

https://qiita.com/zumax/items/a8541406f59ab477a4af


# 実践
## バケットの作成
事前に、S3へ音声ファイルをアップしておきます

1. S3バケットを作成します
1. 音声ファイルをアップします
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/c00310e0-9ede-46be-a6b3-a1c8c2270dfa.png)

## トランスクリプションジョブ
1. Transcribeを開きます
1. ナビゲーションペインで、トランスクリプションジョブをクリックします
1. 特定の言語を入力します
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/a3bc2894-0b66-4a5b-8ff1-17d672c306fe.png)

1. 音声データをアップしたS3パスを指定します
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/398a0d78-c687-47a4-8580-194604608b63.png)

1. 出力するバケットを指定します
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/dcd8ca37-beb0-4800-b211-09c1021fee90.png)

1. 次へ
1. ジョブを作成をクリックします
1. 進行中になりました
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/b83f2aa9-269b-4fa0-b565-bc52efa17b3e.png)
1. すぐに完了になります
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/03ec4c3d-72ab-425c-a9e6-2adf7e8f7666.png)

1. 出力されました
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/10988269-b866-4595-9cc0-7f02d0d11328.png)


## JSONを加工
そのままだと、扱いづらいのでテキストだけ抽出します
1. ローカルにJSONをダウンロードします
1. 下記のスクリプトを実行します
    ```py
    import json
    
    # TranscribeのJSONファイルを開く
    with open('MyTranscribeJob.json', 'r', encoding='utf-8') as f:
        data = json.load(f)
    
    # テキストだけを連結して表示
    full_text = ' '.join([item['transcript'] for item in data['results']['transcripts']])
    print(full_text)
    ```
1. 文字列が抽出できました（都合上、ここには載せておりません。）


# 考察
次回は、OpenAIのwhisperをためしてみようとおもいまｓ

https://github.com/openai/whisper


# 参考


https://github.com/openai/whisper

https://qiita.com/zumax/items/a8541406f59ab477a4af

https://docs.aws.amazon.com/ja_jp/transcribe/latest/dg/what-is.html
フルテキスト検索の仕組みを理解する



## はじめに

フルテキスト検索は、現代の検索エンジンやデータベースシステムにおいて重要な技術です。単純な文字列マッチングとは異なり、言語的な特性を考慮した高度な検索を実現します。

本記事では、フルテキスト検索の内部処理について、3つのステップに分けて詳しく解説します。

## フルテキスト検索とは

**フルテキスト検索**とは、単純な完全一致検索ではなく、
テキスト内容を言語的に分析して検索する手法のことです。

### 従来の検索との違い

```
従来の検索: "hotel" → "hotel"を含む文書のみヒット
フルテキスト検索: "hotel" → "hotel", "hotels", "Hotel"なども含めてヒット
```

## フルテキスト検索の処理フロー

フルテキスト検索は以下の3つのステップで処理されます：

```
ユーザー入力 → ①クエリ解析 → ②字句解析 → ③ドキュメント取得＆スコアリング → 検索結果
```

---

## ①クエリ解析（Query Parsing）

### 概要
ユーザーが入力したクエリを、実際の検索処理で使用するワードに変換する作業です。
最終的に抽象構文ツリー（AST）に変換されます。

### 主要なクエリタイプ

#### 1. 用語クエリ（Term Query）
単一の単語を検索するクエリ

```
入力: hotel
処理: "hotel"という単語を含む文書を検索
```

#### 2. フレーズクエリ（Phrase Query）
引用符で囲まれた複数単語の完全なフレーズを検索

```
入力: "free parking"
処理: "free"と"parking"が隣接して現れる文書を検索
```

#### 3. プレフィックスクエリ（Prefix Query）
指定されたプレフィックス（接頭辞）で始まる用語を検索

```
入力: air*
マッチ: airport, airline, air-conditioning など
```

### クエリ解析の例

**入力クエリ**: `"luxury hotel" AND air* OR parking`

**抽象構文ツリー（AST）**:
```
         OR
        /  \
      AND   Term
     /  \   (parking)
  Phrase  Prefix
("luxury hotel") (air*)
```

---

## ②字句解析（Lexical Analysis）

### 概要
クエリ用語とドキュメント内のテキストを、言語ルールに基づいて正規化し、検索精度を向上させる処理です。

### 主要な処理

#### 1. 小文字への変換
```
Hotel → hotel
FREE → free
```

#### 2. ストップワードの除去
検索に不要な一般的な単語を除去

```
日本語: は、が、の、です、ます
英語: the, a, an, is, are
```

#### 3. 語幹抽出・原型変換
単語を基本形に変換

```
英語: comfortable → comfort, running → run
日本語: 走っている → 走る, 美しかった → 美しい
```

#### 4. 複合語の分割
```
air-conditioning → air + conditioning
駅前ホテル → 駅前 + ホテル
```

### 字句解析の効果

**入力**: `"comfortable hotels"`
**解析後**: `"comfort hotel"`

これにより、文書内に「comfort hotel」「comfortable hotel」「hotels with comfort」などがあっても、すべてヒットするようになります。

---

## ③ドキュメント取得＆スコアリング

### 概要
処理されたクエリに基づいて関連するドキュメントを取得し、関連度に応じてスコアリングを行います。

### ドキュメント取得
- 字句解析されたクエリ用語をインデックスと照合
- 一致するドキュメントセットを特定

### スコアリング
各ドキュメントに関連度スコアを付与。一般的に**TF-IDF**アルゴリズムが使用されます。

#### TF-IDF の構成要素

**TF（Term Frequency）**: 用語頻度
- ドキュメント内でのキーワード出現回数
- 多く出現するほど関連度が高い

**IDF（Inverse Document Frequency）**: 逆文書頻度
- 全体での用語の希少性
- 珍しい単語ほど重要度が高い

#### スコアリング例

検索語：「機械学習」

```
文書A: 「機械学習」が5回出現、全体で「機械学習」を含む文書は少ない
→ 高スコア

文書B: 「機械学習」が1回出現、全体で「機械学習」を含む文書は多い
→ 低スコア
```

### 結果の並び替え
スコアの高い順にドキュメントを並び替えて、ユーザーに提示します。

---

## 具体的な処理例

### 入力クエリ
```
"東京 ホテル" 駅近 安い
```

### ①クエリ解析
```
フレーズクエリ: "東京 ホテル"
用語クエリ: 駅近
用語クエリ: 安い
```

### ②字句解析
```
"東京 ホテル" → "東京 ホテル" (フレーズはそのまま)
駅近 → 駅近
安い → 安 (語幹抽出)
```

### ③ドキュメント取得＆スコアリング
1. 「東京 ホテル」というフレーズを含む文書を検索
2. 「駅近」「安」を含む文書を検索
3. 各文書にTF-IDFスコアを計算
4. スコア順に結果を返却

---

## まとめ

フルテキスト検索は以下の3つのステップで実行されます：

1. **クエリ解析**: ユーザー入力をASTに変換
2. **字句解析**: テキストの正規化と言語処理
3. **ドキュメント取得＆スコアリング**: 関連文書の特定と関連度算出

これらの処理により、単純な文字列マッチングでは実現できない、柔軟で精度の高い検索が可能になります。

現代の検索システム（Elasticsearch、Solr、Azure AI Searchなど）は、すべてこの仕組みを基盤として構築されており、理解することで効果的な検索システムの設計・運用が可能になります。

## 参考情報

- Lucene：オープンソースの全文検索ライブラリ
- Elasticsearch：分散型検索・分析エンジン  
- Azure AI Search：Microsoft Azureの検索サービス
郵便番号・デジタルアドレスAPIを10行で実装し、Vercel Functionsにデプロイする

```javascript:api/searchcode.js
export async function GET(request) {
  const body = JSON.stringify({
    grant_type: 'client_credentials',
    client_id: 'your-client_id',
    secret_key: 'your-secret_key'
  })
  const headers = { 'Content-Type': 'application/json', 'x-forwarded-for': '127.0.0.1', 'User-Agent': 'Mozilla/5.0' }
  const tokenRes = await fetch('https://api.da.pf.japanpost.jp/api/v1/j/token', { method: 'POST', headers, body })
  const { token } = await tokenRes.json()
  const search_code = new URL(request.url).searchParams.get('search_code')
  const searchRes = await fetch('https://api.da.pf.japanpost.jp/api/v1/searchcode/' + search_code, { headers: { 'Authorization': 'Bearer ' + token, 'User-Agent': 'Mozilla/5.0' } })
  const res = new Response(searchRes.body, searchRes)
  res.headers.set('Access-Control-Allow-Origin', '*')
  return res
}
```

```json:vercel.json
{
  "public": true,
  "regions": ["hnd1"],
  "rewrites": [
    { "source": "/:search_code", "destination": "/api/searchcode?search_code=:search_code" }
  ]
}
```

api.da.pf.japanpost.jpはap-northeast-1のEC2でExpressサーバーで実行されているので、hnd1を指定すると吉

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/790dfd88-0aa3-495c-9a3b-9bebfc29e34b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/c72f0b56-27b4-4055-8ccc-c3bd3d0a9548.png)

https://mxtoolbox.com/SuperTool.aspx?action=a%3aapi.da.pf.japanpost.jp&run=toolpage

# システム登録の固定IPアドレスは127.0.0.1に設定しよう！

`'x-forwarded-for': '127.0.0.1'`で実行するとAWSでもGCPでもGoogle Apps Scriptでも動く！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/c5b8a364-d193-4e61-b142-319a9990f72d.png)

# 使い方

```bash
curl https://jp-chi.vercel.app/1000001
```

```javascript
await fetch('https://jp-chi.vercel.app/1000001').then(r=>r.json())
{
    "page": 1,
    "limit": 1000,
    "count": 1,
    "searchtype": "zipcode",
    "addresses": [
        {
            "dgacode": null,
            "zip_code": "1000001",
            "pref_code": "13",
            "pref_name": "東京都",
            "pref_kana": "トウキョウト",
            "pref_roma": "TOKYO",
            "city_code": "13101",
            "city_name": "千代田区",
            "city_kana": "チヨダク",
            "city_roma": "CHIYODA-KU",
            "town_name": "千代田",
            "town_kana": "チヨダ",
            "town_roma": "CHIYODA",
            "biz_name": null,
            "biz_kana": null,
            "biz_roma": null,
            "block_name": null,
            "other_name": null,
            "address": null,
            "longitude": null,
            "latitude": null
        }
    ]
}
```
[Data Cloud のクレジット消費量




+ [Data Cloud のクレジット消費量を Flow で監視する](https://cloud.flect.co.jp/entry/2025/05/29/100000)

+ TenantDailyEntitlementConsumption
+ TenantHourlyEntitlementConsumption
+ TenantEntitlementTransaction

+ [Consumption Cards Reporting across multiple Data Cloud Orgs](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000TjPnj0AF)
Messaging Templates Error Log


+ [Messaging Components- Error Logs](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000SWqkH)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/dcf9c7c7-7b00-4d11-bdd5-63e2948d794d.png)

:::note
https://www.infallibletechie.com/2025/01/track-salesforce-send-conversation-messages.html
:::
Spring Boot API設計の基本！パスパラとクエリパラメータの違いをサンプルで理解する

# パスパラメータとクエリパラメータの違いと使い分け

Spring BootでURLにパラメータを渡す方法は主に2つあります。

1. **パスパラメータ（@PathVariable）**  
2. **クエリパラメータ（@RequestParam）**

---

## 1. パスパラメータ（@PathVariable）とは？

パスパラメータはURLのパス部分に値を直接埋め込みます。  
例えば、`/api/user/123` のように、`123`がユーザーIDを示す場合です。

- **用途**：リソース（ユーザーや商品など）の「識別子」を指定するときに使います。 
- **特徴**：URLの構造が変わるためREST設計ではリソースの場所を表現するのに適しています

Spring Bootのコード例では、以下のように書きます。

```java
@GetMapping("/api/user/{id}")
public Map<String, Object> getUserById(@PathVariable Long id) {
    // idを使って処理
}
```

## 2. クエリパラメータ（@RequestParam）とは？

クエリパラメータはURLの末尾に`?`で始まるパラメータを付けて送る方法です。
例えば、`/api/user?id=123&name=山田太郎` のように複数の値を渡せます。

- **用途**：検索条件やフィルター、オプションの値など、リソースの識別子以外の値を渡すのに適しています
- **特徴**：パラメータはオプションとして指定でき、値がなくてもリクエスト可能です

Spring Bootのコード例では、以下のように書きます。

```java
@GetMapping("/api/user")
public Map<String, Object> getUserByQuery(
    @RequestParam(name = "id", required = false) Long id,
    @RequestParam(name = "name", required = false) String name) {
    // idやnameを使って処理
}
```

`required = false`を指定すると、そのパラメータは無くてもエラーになりません。

## 画面からの呼び出し例（jQuery）

+ パスパラメータ

```java
$.ajax({
  url: '/api/user/123',
  type: 'GET',
  success: function(response) {
    console.log(response);
  }
});
```

+ クエリパラメータ

```java
$.ajax({
  url: '/api/user',
  type: 'GET',
  data: { id: 123, name: '山田太郎' },
  success: function(response) {
    console.log(response);
  }
});
```

## まとめ
| 種類            | URL例                      | 主な用途                    | 特徴                       |
|-----------------|----------------------------|----------------------------|----------------------------|
| パスパラメータ   | `/api/user/123`            | リソースの識別子（IDなど） | URLの一部として必須         |
| クエリパラメータ | `/api/user?id=123&name=山田` | 検索条件やフィルターなど    | 任意のパラメータとして扱える |
Leafletで"Uncaught TypeError: Cannot read properties of null (reading '_latLngToNewLayerPoint')"が出力される

## 環境
- [Vue](https://ja.vuejs.org/) 3.4.21
- [leaflet](https://leafletjs.com/) 1.9.4

## 事象
leafletでOpenStreetMapを表示し、その上にピンを描写。
その状態で下記動作を行うことでエラー発生。
- ズームイン/アウトを高速で繰り返す
- 同コンポーネントの状態が変更するような動作（例えばプルダウンを表示する等）をした直後にズームを行う

### エラー内容
```
Uncaught TypeError: Cannot read properties of null (reading '_latLngToNewLayerPoint')
    at e._animateZoom (Tooltip.js:209:23)
    at e.fire (Events.js:195:9)
    at e._animateZoom (Map.js:1701:8)
    at e.<anonymous> (Map.js:1679:9)
```

## 原因
結論としてはleafletのバグのようです。
エラー主力された`/leaflet/src/layer/Tooltip.js`の該当処理を見てみると、
`this._map._latLngToNewLayerPoint`を呼び出そうとしています。
この時に`this._map`がnullなのでエラーが発生している模様。
```js
_animateZoom: function (e) {
    var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
    this._setPosition(pos);
},
```
恐らく負荷をかけて処理が遅くなる、コンポーネント再読み込みなどのタイミングで`this._map`が格納される前にズーム処理が動いているのが原因かと思います。
Issueにも同様の不具合が報告されていました。
[Fix issue with _latLngToNewLayerPoint #8574](https://github.com/Leaflet/Leaflet/pull/8574)

## 対策
上記のIssueにもありますが、問題のメソッドをオーバーライドして実行前に`this._map`が存在するかチェックすることで解消しました。
具体的には下記のコードを追記しました。
```ts
<script lang="ts" setup>
import { ref } from 'vue'
import L from 'leaflet'

// ここから
L.Tooltip.prototype._animateZoom = function (e: any) {
    if (!this._map) {
        return
    }
    let pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center)
    this._setPosition(pos)
}
L.Tooltip.prototype._updatePosition = function () {
    if (!this._map) {
        return
    }
    let pos = this._map.latLngToLayerPoint(this._latlng)
    this._setPosition(pos)
}
// ここまでを追加

const map = ref<any>()

// 地図描写処理 etc.
</script>
<template>
...
</template>
```

## 参考
- [Fix issue with _latLngToNewLayerPoint #8574](https://github.com/Leaflet/Leaflet/pull/8574)
- [Leaflet error when zoom after close popup in lightning component](https://salesforce.stackexchange.com/questions/180977/leaflet-error-when-zoom-after-close-popup-in-lightning-component)
OpenMediaVault on Raspberry Pi 4 インストールメモ

# 個人的メモ
1. Raspberry Pi OS Lite を焼く
   - Desktop 環境だと OMV に拒否される
2. OMV Install
   - https://github.com/OpenMediaVault-Plugin-Developers/installScript
   - https://wiki.omv-extras.org/doku.php?id=omv7:raspberry_pi_install
3. reboot
4. GUI Login
   - username `admin`
   - password `openmediavault`
5. メール設定
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278058/e0f39304-d614-424b-9d9c-76abbf0d963c.png)
6. ファイルシステムマウント
7. ディスクの smart 有効化
    ```sh
    sudo smartctl --smart=on /dev/sda
    sudo smartctl --smart=on /dev/sdb
    sudo smartctl --smart=on /dev/sdc
    sudo smartctl --smart=on /dev/sdd
    sudo smartctl --smart=on /dev/sde
    ```
8. smart 設定
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278058/3f140d65-2933-4495-9be6-19a8850396c7.png)
9. mdadm の整合性チェック設定
    ```sh
    $ cat<<__EOF__ | sudo tee /etc/systemd/system/mdadm-scrub.service
    [Unit]
    Description=check /dev/md0
    
    [Service]
    Type=oneshot
    ExecStart=/usr/bin/bash -c 'echo check > /sys/block/md0/md/sync_action'
    __EOF__
    
    $ cat <<__EOF__ | sudo tee /etc/systemd/system/mdadm-scrub.timer
    [Unit]
    Description=mdadm check every 2 weeks on Sunday at 00:00
    
    [Timer]
    OnCalendar=Sun *-*-01,14 00:00:00
    Persistent=true
    
    [Install]
    WantedBy=timers.target
    __EOF__
    
    $ sudo systemctl daemon-reload
    $ sudo systemctl enable --now mdadm-scrub.timer
    ```
10. 共有フォルダ設定
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278058/5510bf4b-f1f8-403f-89c6-6eda403faa99.png)
11. rsync module 設定
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278058/a93b6dec-4c08-4dfe-8d5c-d8d3e2a438b4.png)
QGISでOpenLRを可視化するプラグイン（Pythonスクリプトベース）

こんにちは。  
本記事では、OpenLR形式で記述された位置情報をQGIS上で可視化するプラグインを紹介します。

Pythonベースで構築されたOpenLRデコーダ（`openlr-dereferencer`）をもとに、GUIで扱えるQGISプラグインとして実装しました。

## 🔧 目的

- PythonでOpenLRを扱っていたけど、（とりあえず）地図上で結果を見たくなった
- GUIでPostgreSQLに接続 → OpenLRを貼り付け → 地図に表示、を完結させたい

## 🧠 背景：もともとはPythonスクリプトで処理

これまで、以下のような構成でOpenLRをデコードするPythonスクリプトを実装していました。

- PostgreSQL + PostGIS 上に道路ネットワークを構築
- `openlr-dereferencer` を使用してOpenLRをデコード
- 出力はLineStringとして `print()` で確認

この内容については[WestTraffic](https://qiita.com/westTraffic) さんの記事[openlr-dereferencer-pythonを実装してみた](https://qiita.com/westTraffic/items/914401cc1768b37852c1) を参考にさせていただきました。

## 🖥 今回の内容：QGISプラグイン化

このスクリプトベースの処理をQGISのGUIプラグインとして実装しました。

### 主な機能：

- PostgreSQLへの接続情報をGUIで入力
- OpenLR文字列を貼り付けてデコード
- 結果を `Decoded OpenLR Lines` レイヤとして地図に表示


## ✅ 動作確認済み環境

- QGIS LTR 3.34（Prizren）
- Pythonライブラリ：
    - `openlr-dereferencer`
    - `psycopg2`
    - `pyproj`
- PostgreSQL + PostGIS（道路テーブルあり）

## 🔗 プラグインのコード（GitHub）

GitHubにコードを公開しています（※ZIP形式での手動インストール推奨）：

👉 [openlr-qgis-plugin](https://github.com/Sabakuma/openlr-qgis-plugin)


## 📦 インストール方法

1. リポジトリをクローンまたはZIPでダウンロード
2. `__init__.py` を含むディレクトリをZIP化
3. QGIS > プラグイン > プラグインをZIPからインストール
4. QGIS再起動後、プラグインを起動

⚠️ 注意：GitHubには**ソースコードのみ**が含まれています。UIの変更やZIP形式への変換は各自の環境でお願いします。


## ✍ おわりに

OpenLRのような文字列ベースの位置情報を、QGIS上で地図として確認できるのは非常に便利です。  
GUIでPostgreSQLと連携し、OpenLR文字列をその場で可視化できる今回のプラグインは、日常業務やプロトタイピングの中でも役立つはずです。

ご興味ある方はぜひお試しください。


## 🔧 補足：PostgreSQLテーブル構成（参考）

### `roads` テーブル（例）：

| カラム名 | 型 | 内容 |
|----------|----|------|
| id | bigint | 主キー |
| fow / frc | smallint | OpenLR対応の道路属性 |
| flowdir | smallint | 方向（1=両方向, 2=終点→始点, 3=始点→終点） |
| from_int / to_int | bigint | 接続交差点 |
| len | double precision | 長さ（m） |
| geom | LineString(4326) | 位置情報 |
【Figma】共有URLを開くとブラウザが開いちゃう問題をサクッと解決する方法（Mac & Windows）

Figmaのファイルを共有してもらうとき、よくある小さなイライラ。  
**「URLをクリックしたらアプリじゃなくてブラウザで開いちゃう！」**  
…って経験ありませんか？

ブラウザでも作業できるけど、アプリの方がサクサク動くし便利ですよね。  
この記事では、**「共有URLをアプリで直接開く方法」** をまとめます。

---

## 🟢 事象

1. 共有URLをもらう  
2. クリックするとブラウザで開く  
3. アプリで作業したいのにブラウザ上になってしまう…

---

## 🟢 解決方法

### ✅ Macの場合

1. 共有URLをコピーする  
2. Figmaアプリを開く  
3. メニューの「ファイル」→「クリップボードにあるファイルを開く」を選択  
4. これでアプリ上に直接開ける！

![スクリーンショット 2025-05-31 9.53.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557457/c4b3a324-5823-4bcc-85bf-2aefb2a41c94.png)


### ✅ Windowsの場合

1. 共有URLをコピーする  
2. Figmaアプリを開く  
3. 画面右上の**下向き矢印**アイコンをクリック  
4. 「クリップボードにあるファイルを開く」を選択  
5. アプリで直接開ける！

---

## 🟢 まとめ

共有URLをもらったときは、まずコピーしてからアプリ側で「クリップボードにあるファイルを開く」を使うのがコツ！  
これでブラウザに切り替わるイライラも解決です。  
ぜひ試してみてください！
e-Gov与件特性

e-Gov与件をMarkdownに自動変換する仕組みを検討している。

e-Govの与件の誤りの可能性をいくつか散見した。
修正する可能性がある。暫定記録とする。修正後も、履歴として記録は保持する。

e-Gov データエラー集
https://qiita.com/kaizen_nagoya/items/753ecd11d77bbf8ddd61

# 与件特性 原文編
##  法律番号
一つの記事中、法律名が現れた場合には、法律番号を（）書きする。
２度目には、法律番号を記載しない。
## 法律名
法律名は、原則省略しない。ただし、法律文中で省略名を使う場合には、法律番号を記載した（）書きの中で、この法律での省略名を記載する。

### 法律短縮名、通称名
法律短縮名、通称名の記載があるかどうかは、誰がどう決め、どこに記載するかがよくわかっていない。
他の法律での短縮名は、法文中に記載することがある。ただし、その法文中でのみ有効な名前で、他の法律の短縮名と重なるかもしれない。「徴収法」など。

## 改訂・制定法律名
新規制定の場合は、制定法律名と同様。記載はない。

# 与件特性　e-Gov編
官報に記載とe-Gov記載の表現に違いがあれば、記録する。
手元に官報がみあたらず、まだ想定の範囲内。

# Qiita Markdown　記事作成方針
編 #
章 #
節 ##
歓 ###
目 ### （みだし）は、現在###, ####にするなら、目も####
(みだし) ###
表：複雑な線の非表示はしない。各行の横線は表示したままにする。

誤植などは直す。
e-Gov データエラー集
https://qiita.com/kaizen_nagoya/items/753ecd11d77bbf8ddd61

e-Gov与件特性
https://qiita.com/kaizen_nagoya/items/b4b74eb9d87b8d0449c6

@syoyo「e-Gov 法令データ」AI(13)
https://qiita.com/kaizen_nagoya/items/2c561aaaf1e86f5f536b

# 参考資料
社会保険労務士関連法規群
https://qiita.com/kaizen_nagoya/items/699549fc9fca897b33f3
プロデル、調査 その12

# 概要
プロデルが、CLRらしいので、調べて見た。
練習問題やってみた。


# 練習問題
ペイントを、RPAせよ。


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/626dc9ef-7cef-4ac8-8e3c-b90685912b47.png)

# サンプルコード

```
ファイル名は「mspaint.exe」
ファイル名を起動して対象プロセスとする
繰り返す
	起動中プロセス一覧を要素へそれぞれ繰り返す
		要素のタイトルが「ペイント」で終われば
			選択プロセスは、要素
			繰り返しから抜け出す
		そして
	そして
	選択プロセスが無でなければ繰り返しから抜け出す
	0.1秒待つ
	対象プロセスの起動中が○でなければ終了する
そして
1秒待つ
ペイント画面は、選択プロセスのメイン外部ウィンドウ
ペイント画面をアクティブ化する
対象サイズは、ペイント画面の大きさ
マウスカーソルをペイント画面で{対象サイズの幅/2+50, 対象サイズの高さ/2+100}へ移動する
マウスカーソルに左ボタンで押させる
マウスカーソルをペイント画面で{対象サイズの幅/2+250, 対象サイズの高さ/2+100}へ移動する
マウスカーソルに左ボタンで押させる
マウスカーソルをペイント画面で{対象サイズの幅/2+85,対象サイズの高さ/2+ 210}へ移動する
マウスカーソルに左ボタンで押させる
マウスカーソルをペイント画面で{対象サイズの幅/2+150,対象サイズの高さ/2+30}へ移動する
マウスカーソルに左ボタンで押させる
マウスカーソルをペイント画面で{対象サイズの幅/2+215, 対象サイズの高さ/2+210}へ移動する
マウスカーソルに左ボタンで押させる
マウスカーソルをペイント画面で{対象サイズの幅/2+50,対象サイズの高さ/2+100}へ移動する
マウスカーソルに左ボタンで押させる
マウスカーソルに左ボタンで離させる




```

以上。
e-Gov データエラー集

百近い与件確認。３箇所に誤りの可能性。
記録忘れで、後２件は、後日記入。

| 法律 URL|誤植等|訂正想定事項|
|:--|:--|:--|
|下請代金支払遅延等防止法（昭和三十一年法律第百二十号）https://laws.e-gov.go.jp/law/331AC0000000120|改訂法律が法律番号のみ：（平成二十四年法律第百二号）|法律名：年金生活者支援給付金の支給に関する法律|


# 参考資料
e-Gov与件特性
https://qiita.com/kaizen_nagoya/items/b4b74eb9d87b8d0449c6

@syoyo「e-Gov 法令データ」AI(13)
https://qiita.com/kaizen_nagoya/items/2c561aaaf1e86f5f536b

社会保険労務士関連法規群
https://qiita.com/kaizen_nagoya/items/699549fc9fca897b33f3
JavaScriptでの単一メソッドオブジェクトのネスト

# 概要
JavaScriptでは、単一メソッドのみを定義したオブジェクトをネストさせることができます。これで制御されたメソッドチェーンを作れます。
# 定義
```js
const cleanObj = (obj) => Object.assign(Object.create(null), obj);
const nestedObj = {
    a : () => cleanObj({
        b : () => cleanObj({
            c : () => console.log("I am nested!")
        })
    })
}
```

# 使用例
```js
nestedObj.a().b().c(); 
```
# 表示
```text
I am nested!
```

# まとめ
JavaScriptでは、単一メソッドのみを持つオブジェクトをネストさせて、制御されたメソッドチェーンを作ることが簡単にできます。