OmniAICreator/Qiita-1.07M huggingface dataset:
Rails:フォーム送信時のバリデーションエラーがビューに反映されない(ActionController::ParameterMissing (param is missing or the value is empty:)

環境
Ruby:3.2.2
Rails:7.1.5

期待していた動作
・空のemailやpasswordでログインを試みたときに正しくエラーメッセージを表示してほしい
```
  #app/forms/login_form.rb
  class LoginForm
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :email,:string
  attribute :password,:string

  validates :email,presence:true
  validates :password,presence:true
  validate :valid_combination

  def save
    return false if invalid?
    true
  end
  
  private

  # ユーザーが見つからない、またはパスワードに誤りがある場合にエラーを返す
  def valid_combination
    @user = User.find_by(email: email)
    errors.add(:base,'メールアドレスとパスワードの組み合わせが正しくありません') unless @user&.authenticate(password)
  end

  
  
  #app/controllers/session_controller.rb
  def create
    @login = LoginForm.new(session_params)
    if @.save && (@user = User.find_by(email: @.email)) && @user.authenticate(@.password)
      session[:user_id] = user.id
      redirect_to root_url,status: 303,notice: 'ログインしました'
    else
      render :new,status: 422,notice: 'ログインに失敗しました'
    end
  end
  
  
  #app/views/session/new.html.slim
  = form_with model:@login, url:login_path,local:true do |f|
  .form-group 
    = f.label :email, 'メールアドレス'
    = f.text_field :email ,class:'form-control',id: 'session_email'
  .form-group 
    = f.label :password, 'パスワード'
    = f.password_field :password,class:'form-control',id:'session_password'
  =f.submit 'ログインする',class: 'btn btn-primary'
​
```

  
症状
・エラーメッセージの表示なし
・ブラウザで特にエラーは吐かれていない
・サーバー側のコンソールでは400BadRequestが返っている
・paramsオブジェクト内にloginというハッシュが見つからないようだ
```
ActionController::ParameterMissing (param is missing or the value is empty: login):
01:38:38 web.1  | Started POST "/login" for ::1 at 2025-05-05 01:38:38 +0900
01:38:38 web.1  | Processing by SessionController#create as TURBO_STREAM
01:38:38 web.1  |   Parameters: {"authenticity_token"=>"[FILTERED]", "login_form"=>{"email"=>"test", "password"=>"[FILTERED]"}, "commit"=>"ログインする"}
01:38:38 web.1  | Completed 400 Bad Request in 3ms (ActiveRecord: 0.0ms | Allocations: 742)
ActionController::ParameterMissing (param is missing or the value is empty: login):

```

推察
・modelオプションに@loginを渡せばフォームのスコープはloginになると思っていたが、スコープが別のものになっている？
調査
・ブラウザのデベロッパーツールで入力フィールドのname属性を確認した。
name = "[login_form[フィールド名]]"​
のような形になっておりやはり期待していたlogin[フィールド名]の形ではなかった

原因
・フォームのスコープは渡すインスタンス変数の名前ではなくモデルクラス、もといそのファイル名となる

解決策
・モデルクラス名とビューに渡すインスタンス変数名をlogin_formにそろえた
```
  def create
    @login_form = LoginForm.new(session_params)
    if @.save && (@user = User.find_by(email: @.email)) && @user.authenticate(@.password)
      session[:user_id] = user.id
      redirect_to root_url,status: 303,notice: 'ログインしました'
    else
      render :new,status: 422,notice: 'ログインに失敗しました'
    end
  end
```
​
抽象化・一般化
・クラス名とビューに渡すインスタンス変数名は揃えよう
めんどくさいからって短縮しない
Geminiで太鼓を使う魔法少女を描いてみた。

# 概要

Geminiで太鼓を使う魔法少女を描いてみました。

# 実装

プロンプトと実行結果は以下の通りでした。

```
光の太鼓を使う魔法少女を描いてください。
```

![光の太鼓を使う魔法少女_20250505.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/3e0b8427-0e00-481f-aa3f-eeece936e8ea.png)


```
闇の太鼓を使う魔法少女を描いてください。
```

![闇の太鼓を使う魔法少女_20250505.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/a22abcab-2bab-4d45-9ef6-19cf61846a3e.png)


```
聖なる太鼓を使う魔法少女を描いてください。
```

![聖なる太鼓を使う魔法少女_20250505.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/4d50f9d6-6114-42ca-82aa-de22e0838f9b.png)


# まとめ

闇の子は可愛いかも。
何かの役に立てばと。
brew install climaしたあとrossetaのエラーと出たときはhomebrewを再インストールする

homebrew経由でインストールしたとき
`limactl is running under rosetta, please reinstall lima with native arch`
と出たら

もしintel時代からmacを移行し続けいるなら、homebrewが古くなっている

1.  homebrewをアンインストールする(公式よりコマンド実行)
    - https://docs.brew.sh/FAQ
2.  homebrewをインストールする
3. colimaをインストールする
4.  その他ｗ必要に応じてまたインストールする

https://github.com/abiosoft/colima/issues/702#issuecomment-1600029743

# 同じような事象

https://qiita.com/yoshi-taka/items/95580b5dee32aca9f40c
学習開始から2週間の記録方法

## はじめまして！
📌 現在、プログラミングスクールにてWeb開発を学習中です。
🎯 未経験からIT業界へのキャリアチェンジを目指しています。

学習がスタートして2週間。学習の記録としてqiitaを始めます:grinning:

ここまでの間も別なツール（Notion）に気になったことや深掘りが必要そうな事項など、記録をしていました。
そちらを確認して、この2週間分の振り返りから、少しずつ始めてみたいと思います。
よろしくお願いします。


## 学習の記録の手始めにNotionを選んだ理由
ここで、「とりあえずのメモ」に私がNotionを選んだ理由をお話しさせてください。
理由は大きく2つあります。

* 使い慣れていたこと
* データベース機能を使ってキーワードやタグで必要な情報を取り出したかったこと

### Notionへ記録するフロー
![image (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078128/b3c2e9a4-22d3-4860-bf3e-a72614f5204c.png)

1. 記録しておきたい事象が発生する
2. Notionデータベース内、該当のボードビューを開く（添付スクショ）
3. 新規追加→テンプレを選択して入力を開始する
4. 適宜プロパティに入力
5. ChatGPTとのやりとりなど長文は本文にき記載する

### 小さなルール
* 日付と言語は必ず入力する
* 後々の用途を想定してタブ分けする
* タブに応じたプロパティの入力をする

### 使う中で改めてNotionが合うなと思った点
* データベースで管理できるので検索ができる
* 走り書きのようなmemo、コピペでもとりあえず収められる
* タグを設定しておける
* ChatGPTとの親和性が高い（コピペがきれいに反映される）


## Qiitaを始めた理由～Notionだけでは足りない？～
すくーるでの学習を進めつつ、転職活動をします。
未経験エンジニアかつ、業界も未経験、年齢は今年39歳、4歳8歳の育児との兼ね合いでフルリモートを希望しています。状況が厳しいことは重々理解しているつもりなので、少しでもできること、伝えられることは整理して持っておきたいと考えました。

Notionは教材のスクショなども貼っておりそのまま展開するのが難しかったため、
せっかくの機会なのでちょっと忙しくはなりますがQiitaを利用させていただくことにしました。

諸先輩方、同じような状況の方、多くの方の記事へもお邪魔させていただくと思います！
これからどうぞよろしくお願いします！:whale2:
会議に遅れないための3つの具体的な習慣術

## はじめに

「気づいたら会議始まってた…」
「前のミーティングが長引いて、次に遅刻…」
そんな経験、誰にでもありますよね。

私自身、遅刻しがちなタイプなので、「どうすれば減らせるか？」を見直す機会がありました。
この記事では、その中で見つけた工夫をまとめています。

## 1. **Googleカレンダーの通知設定を“自分仕様”に最適化する**

通知音を聞いたけど、作業を続けていたら遅刻してしまうパターン。
集中していると、「通知＝今すぐ移動」にならず、気づいたら数分過ぎていることも…。

### ✅ 対策：カスタム通知を設定しよう

* 予定ごとではなく「**マイカレンダー全体の通知設定**」で一括変更可能
* 例：**10分前・5分前・2分前**の3段階通知（音付き）を設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/505972/a08da84f-cf88-4d03-b26b-1e38fc5190ea.png)


通知の間隔を工夫することで、直前に集中していても「3段階で気づける」ようになります。

## 2. **通知が来たら“すぐ入る”という習慣をつける**

会議の時間ちょうどを狙って入ろうとすると、PCの不調や他の作業でうっかり遅れる可能性が高くなります。

### ✅ 対策：2分前 or 5分前に入って“待機モード”へ

* 通知が来たら、そのまま会議室に入る
* 音声・カメラのチェックにも使える
* 入室後は、他の人が入ってくるまで画面オフ・マイクミュートで作業を続ける手もある

特にオンライン会議では、**早めの入室にデメリットはほとんどありません**。

## 3. **長引きそうな会議の後にすぐ別の会議を入れない**

前の会議が押してしまって、次の予定に遅刻するのはありがちなケースです。
特に「議題が多い」「人数が多い」「毎回時間通りに終わらない」会議の後は、**バッファなしで会議を詰め込むのはリスキー**です。

### ✅ 対策①：あらかじめバッファを設ける

* **長引きそうな会議の後には予定を入れない**ようにするのがベスト
* やむを得ず入れる場合でも、**10分以上の余白**を設けておく

### ✅ 対策②：それでも遅れそうなときは“即連絡＋リスケ判断”

* 5分以上遅れそうな時点で、まずは**チャットなどで一報**を入れる
* 10分以上遅れそうな場合は、**リスケを提案する**のも誠実な対応

例：

> 「前の会議が延長しており、5分ほど遅れそうです。申し訳ありません。」
> 「10分以上押しそうなので、可能であれば別の時間をご相談できればと思います。」

## おわりに
これらの対策を実践しながら、少しずつ遅刻を減らしていきたいと思います。
同じような悩みを抱える方の参考になれば嬉しいです。

## 番外編
- ヘッドホンやイヤホンを外していたことで通知に気づかない
- 音楽を聴いていて通知音がかき消される問題
今更だがDifyに入門するぜ！コミュニティ版で。

こんばんは、座禅いぬです。

**NotebookLM、やばいですね**。要約＋音声化＋対話形式という学習の最適解みたいなサービス。しかも無料。時代に感謝としかいいようがないですね。

そろそろ実務でも生成AIを使うのが当たり前の時代になってきているんじゃないでしょうか？驚いているだけじゃ何も生み出さないですし、どんどん手を動かしていきましょう。というわけで、**今回は一番手軽に生成AIで無双できる手段としてDifyに取り組みました**のでその挑戦した小ネタメモです。

## まず本を買います
### そこはNotebookLMじゃないのかよ！
...って話になりそうですが、本も人類が磨き上げてきた学習の最適解だと思います。選んだのはこれ。

https://amzn.asia/d/1wXpRbC

なおアフィリンクとかじゃないので安心してリンク踏んでください。

### どんな本だった？
とにかくライト級という印象の書籍です。コード的なものは一切出てきませんし、API KEYの取得法も丁寧に解説してくれているので、**非エンジニア向けに特化**していると思います。「**断固今日一日でDifyを習得する**」という使い方にもオススメかなと思います。実際余裕をもって一日で終わりました。

僕はLangChain/LangGraph本読んでる途中だったので、同一著者の本を選びましたが、[同時期に出た他の本との比較記事](https://zenn.dev/arrowkato/articles/dify_book_comparison)を書いてらっしゃる方もいたのでご参考に選んでいただくとよいかと。

## 実務で使うつもりで環境を作ろう ー  AWSで。

### DON'T PANIC。簡単だよ。
AWSのハンズオンがありました。CloudFormationで何も考えなくてもデプロイできます。

- [Dify での生成 AI アプリケーション構築ワークショップ](https://catalog.us-east-1.prod.workshops.aws/workshops/95a3c231-2064-4a33-9a3d-624b7c11aaa6/ja-JP)

これ**めちゃくちゃ便利**ですよ。EC2作らなきゃとか、コンテナどうしようとか色々考えてたのですが、ハンズオンの**指示通りに操作＋yamlのコピペするだけ**で一瞬でした。なお、実際の実務環境のためにはセキュリティの問題があるシンプル構成なのですが、どうしたら安心かもちゃんと説明してくれてます。最高。

実務に向けてハードル下げた状態でスタートできるのがとても素晴らしいのですが、それだけではなくクラウド版の「アプリ５個しかつくれないよ」という制約がないのもいいです。もちろんつくったアプリは**エクスポートして保存できますけど、その手間よりCloudFormationの方が楽**ってレベルです。

### 実際アプリを作ってみる
本に沿って以下のアプリを作成しました。
1. 営業電話のトレーニングアプリ
2. 領収書を表形式で読み取るアプリ
3. 会議の議事録を文字起こしして要約するアプリ
4. 稟議申請の分類とレビューをするアプリ
5. RAGとかSlack連携とか

他にも[公式ドキュメント](https://docs.dify.ai/ja-jp/introduction)に作例として「[チャットストリームエージェントを使用した Twitter アカウントの分析方法](https://docs.dify.ai/ja-jp/workshop/intermediate/twitter-chatflow)」などもあります。

## 試してどうだった？（本）
### 難易度は心配なかった
自分は非エンジニアで若干Pythonのコード書けるぐらいのレベル感なのですが、とにかく今回話題にしている範囲内はコードも書くことなくスムーズでした。
Dify自体も非常にとっつきやすくて面白い！

### 気になったところと解決策
- アプリに実際送るサンプルデータのようなものがない？稟議書など。→**自分で生成AIで作成すればOK！**
- P97 栄養管理士→管理栄養士？
- P121 分析姿勢の項目が途中で途切れてるかも？→P131の別のプロンプトを参照

総じて**わかりやすく、すぐ始められる良書**でした！

## 参考資料

### 本と合わせて参考になる動画

- [【Difyエキスパート3人登壇】プログラミング不要！業務効率を5倍にするAIアプリの作り方](https://www.youtube.com/watch?v=nZ8F2q4e2Us)

上記書籍の著者による本の発売イベントみたいですね。本の狙いやDifyのなにがよいのか？の話。

- [【Dify実践入門】ノーコードで作るAIアプリ4選を元著者がデモ解説！経費精算・営業支援・稟議書処理が驚くほど簡単に | 清水れみおさん | @lemilemilemio](https://www.youtube.com/watch?v=XQG4Ciyvb5I)

さらに、デモしながら解説してくれる動画がありました。20分程度の長さなので、これみてから購入決めてもいいかも。

- [【業務効率化】Dify×Excel×LINE連携の完全ガイド！稟議書も自動化できるプラグイン技術| 清水れみおさん | @lemilemilemio](https://www.youtube.com/watch?v=R2JvYMcaArs)

続けて、プラグイン活用例を紹介されています。本だとMarkdownの表をコピペしないといけないのですが、直接Excel形式で出力したりLINE Botを操作したりと、本の延長線上での応用例の話。この動画を見るところまでセットで本を勉強するほうがよいなとおもいます。

### その他Dify関係の勉強になる資料
- [気になる記事を効率的に情報収集！～ 「Googleアラート⇒GAS⇒Dify要約⇒Slack」の実装～](https://note.com/m_r_k_w/n/n26698cd1c4b4)

M_R_K_Wさんの記事。以前にも紹介しましたが、DifyとSlackの連携で情報収集の効率化をする記事です。結構周りで試している人がいて、実際に情報収集が楽になっていい！と好評です。

- [続・気になる記事を効率的に情報収集！～ HuggingFace Daily Papers編～](https://note.com/m_r_k_w/n/nd95faaf5cdfb)

さらに続編が公開されました！arXivのAI関連の論文の中から厳選→日本語要約→Slackにポスト、という仕組みが自分で作れます。コード書かなくてもコピペでOK。
大学生が初RubyKaigiに参加してみた感想

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078488/1f51024f-9acc-45c4-a06c-4895a653ea32.png" width=70%>

こんにちは！ヤス([@Yasu_Fumi_](https://x.com/Yasu_Fumi_))です！
この記事では、エンジニア歴１年未満でRubyをあまり書いたことない私がRubyKaigi初参加した視点で感想やらを書いていければと思います。
RubyKaigiに参加しようとしている学生さんや、エンジニア歴があまり長くない方の参考となったらうれしいです！！

### 参加に至ったきっかけ
そもそもRubyKaigiという存在を知ったのは今年の２月でした...
大学の授業のひとつに、情報分野で活躍している卒業生の方を招いた特別講義に参加していた際に、Rubyコミッタ―である松本宗太郎さんの講義で知りました。

宗太郎さん：
「学生支援を行ってる会社があるから、興味あったら応募してみてね！無料でいけるよ！」

愛媛！？！？無料でいける！？！？カンファレンスで色んな人と出会えるじゃん！！
応募するしかないでしょ！という勢いでSTORESさんの学生支援に応募しました。
面接を経て、無事にRubyKaigi2025への参加が決まりました。

https://product.st.inc/entry/2025/02/03/142538

### STORES社員・学生支援の他学生との初対面
技術系のカンファレンス自体初参加の私にとって、社員の方や他学生に会うことにとても緊張していました。「技術の話しかしなかったらどうしよう...」「どうせ他の学生はめっちゃ技術に精通して話が合うのかな...」なんていう不安ばかりでした。

こんな不安を抱えて他メンバーと会いにご飯会場へやってきたのですが、びっくりするほどSTORESの社員の方に温かく迎え入れていただきました！また、他の学生ともすぐ仲良くなれてめちゃくちゃ安心しました。おいしいご飯とお酒とともに、すぐ心の壁がなくなりました！

### 会場の雰囲気・セッション感想
とても人が多く、色んな企業がブースを出していて、企業の方々とお話することができました！とくに、私は就活していて、オンライン上で話したことのある人事の方と対面で会うなど、様々な出会いがありました！！個人的にシール集めが大好きで、たくさんのシールを集めることができて超うれしかったです！！

セッションに関して、正直何を言っているのかほとんどわからなかったです。(他の参加者にも聞いたのですが、内容わかっている人ほとんどいなかったです笑)
しかし、そんな中、真剣に聞いていくうちに漠然としたなにかを感じ取れた気がします。プログラミング言語は、私たちの知らないところで誰かが努力してつくりあげていっているのだと。私の見えているところってたったの表面の部分だけだったんだなということを感じました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078488/ae5cbe5c-e2eb-4b9e-9cd5-43c73a33af66.png)

### Official Party・Drink up
今回の Official Party は城山公園 やすらぎ広場というところで開催されました。会場から松山城が見えてとてもきれいでした！料理もとてもおいしく、クラフトビールが飲み放題だったのが、ビール超大好き人間である私からして最高に良かったです。残念だった点としては、料理が思ったよりもすぐ無くなってしまった点と、参加者が結構団体で固まっている印象で、なかなか知らない人との交流がしづらかった点です。
絶対一人で参加はしないほうがいいと思います。

Drink upはQiitaさんとさくらインターネットさん主催のところに参加しました。Drink upはOfficial Partyとは違ってラフに色んな人と交流できる雰囲気でした！学生であるというところを最大限に生かして、たくさん可愛がられました笑

Qiitaさんのところでは愛媛県でとれた海鮮や釜めし、さくらインターネットさんのところでは立食パーティーの形式で豪華な食事が出てきました！！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078488/4cb8fb80-e231-47a5-ac28-cf847af485f2.png" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078488/b62f0a63-2210-4a07-9c71-5e9894eaa40c.png" width=45%>

### 最終日
最終日はふらっと散策をしました！
地元のお寿司屋さんへ行って、大将とおしゃべりしながら地元でとれたて海鮮を食べ、お土産を買ったりしました。

こういったカンファレンスを期に、行ったことのない街へ行き、地元の人と関わるというのは本当にいい経験になります！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078488/a861ea28-5afd-4cb8-a28f-217920f151ee.png" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078488/d828f41f-0838-48a3-bab8-d54eb1ffb82b.png" width=45%>

### 最後に
まず、STORESの皆様本当にありがとうございました。皆様のご支援のおかげで、大変貴重で大事な思い出を作ることができました。

そして、[@irdx_m](https://x.com/irdx_m)さん[@nakiymRuby](https://x.com/nakiymRuby)くんありがとう！！思った以上に2人と仲良くなれて、本当に楽しい時間を過ごすことができました！

来年は北海道で開催するみたいです！少しでも興味ある学生はぜひ参加してみてください！！めちゃお勧めします！！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078488/75d2c384-c400-4d42-96dc-d98fe9887e43.png" width=45%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078488/fd4a468a-3f72-4a95-9f78-a3a5f174f207.png" width=45%>
uvって？

## はじめに
pythonの開発環境について、最近(2025/05/04時点)が注目されている。という話を聞いたので実際に調査＆環境構築までやってみました。この記事ではその調査内容や手順を簡単にまとめます。

## 筆者の環境
- Ubuntu 24.04.2 LTS

## 【調査】uvってなんだ？
uvの特徴を簡単にまとめます。
- **仮想環境を作成・管理**する統合ツールのようなサービス
- Rustで書かれた高速なPythonパッケージマネージャーと仮想環境マネージャー
- 位置づけとしては pip + venv + pip-tools + α の統合ツールのような存在

## 【調査】Pyhtonのバージョン管理方法
プロジェクトごとに異なるPythonのバージョンを用意したい場合は、あらかじめpyenvを用意する必要があるみたいです。

pyenvに関する紹介を行うと長くなるのでインストール~任意のpythonバージョンの用意までのコマンドを残しておきます。

```python
# 1.pyenvのインストール
curl https://pyenv.run | bash

# 2.パスの登録
vim .bashrc

# ここから
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
# ここまでをペースト

# 3. 読み込み
source ~/.bashrc

# 4. インストール可能なpythonのバージョンをチェック
## grepを使うと良
pyenv install -list

# 5. 必要なバージョンをインストール
## 例としてpython3.12.10
pyenv install 3.12.10

# 6. インストール済み価格人
pyenv versions
```

## 【実行コマンド】
ここからは、uvのインストール〜パッケージの追加までｎ実際に使ったコマンドを記載してゆく

```python

# 1.uvのインストール
curl -LsSf https://astral.sh/uv/install.sh | sh

# 2. 新規プロジェクトの追加
uv init my_project
cd my_project

# 3. 新規プロジェクトファイルの追加
## mkdirコマンドで作りがちだが、
## このコマンドで作ることでpyproject.tomlやmain.pyなどもセットできる
uv init my_project
cd my_project

# 4. 仮想環境の作成
## このコマンドで.venvがインストールされ仮想環境が作成される
## 体感的にだがかなり早い印象を受けた
uv venv

# 5. パッケージの追加
## 目的に依存する。例としてpandas
uv add pandas
```
```python
# 補足
pandasをインストールすることでpyproject.tomlが下記の様に更新される
:~/my_project$ cat pyproject.toml 
[project]
name = "my-project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
    "pandas>=2.2.3",
]
```
【GitHub】GitHub Actionsのsecretsを設定する方法


## 設定方法

1. リポジトリの「Settings」をクリック
2. 「Secrets and variables > Actions」をクリック
3. 「New repository secret」をクリック

![4B143EF9-D87B-4243-B34C-BA15C3812F2B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/ee71dd82-44b1-4217-8dc1-cfa65c278190.png)

4. secretの名称を入力
5. secretの値を入力
6. 「Add secret」をクリック

![D992063C-30C6-4D1B-89B6-0EAA9B38634C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/d92fd0f7-d3b6-4138-bdb8-f1b50302a853.png)

## secretsを使用する

設定したsecretsを使用するには`${{ secrets.シークレット名 }}`のようにします。

```yaml
steps:
  - name: Hello world action
    with: # Set the secret as an input
      sample_secret: ${{ secrets.SAMPLE_SECRET }}
```

## 参考

https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository
# React Native × Gemini AI × GCP で作る、カメラで食事のカロリーを分析するアプリ「Cal Food AI」

# React Native × Gemini AI × GCP で作る、カメラで食事のカロリーを分析するアプリ「Cal Food AI」

## はじめに

「Cal Food AI」というアプリを開発しました。  
このアプリでは、**スマホのカメラで撮影した食事写真をAIが分析し、カロリーと栄養素を推定**してくれます。

本記事では、Gemini AIやGoogle Cloudなどの技術を使った開発の流れについて紹介します。

---

## 背景

食事管理アプリは多くありますが、多くが手入力やバーコードスキャンが必要です。  
より直感的で手軽な方法として「写真を撮るだけで栄養情報を取得できる仕組み」を目指しました。

---

## 使用技術スタック

- **フロントエンド**: React Native (Expo)
- **アプリ内課金**: RevenueCat
- **AIモデル**: Gemini Pro Vision (Google AI Studio経由)
- **バックエンド**: NestJS
- **インフラ**: Google Cloud Run, Google Cloud Storage

---

## アーキテクチャ概要

1. ユーザーがアプリで食事を撮影  
2. 撮影画像は Google Cloud Storage に一時保存  
3. Cloud Run 上の NestJS バックエンドが画像を Gemini Vision API に送信  
4. Gemini が食品を推定し、該当する栄養情報（独自DB or API）を返す  
5. ユーザーに総カロリーと栄養素を表示

---

## 実際のスクリーンショット

![screenshot1](https://is1-ssl.mzstatic.com/image/thumb/PurpleSource221/v4/f8/cb/f4/f8cbf47e-11b7-0497-f09f-6d48ff6a560c/_U1109_U1173_U110f_U1173_U1105_U1175_U11ab_U1109_U1163_U11ba_U002c_2025-04-14__U110b_U1169_U110c_U1165_U11ab_2.13.05.jpeg/230x0w.webp)

![screenshot2](https://is1-ssl.mzstatic.com/image/thumb/PurpleSource211/v4/ef/dc/78/efdc7861-f901-1ed2-12ec-1f2cc907c1d8/_U1109_U1173_U110f_U1173_U1105_U1175_U11ab_U1109_U1163_U11ba_U002c_2025-04-14__U110b_U1169_U110c_U1165_U11ab_2.12.22.jpeg/230x0w.webp)

---

## Gemini AI の活用例

Gemini API からは以下のようなレスポンスを取得します：

```json
{
  "food_items": ["grilled chicken", "brown rice", "broccoli"],
  "estimated_calories": 580
}
Gemini は複数の食材を同時に認識し、それぞれのカロリー計算が可能です。

RevenueCatでの課金管理
アプリ内のプレミアム機能（例：履歴管理やデイリーレポート）は RevenueCat 経由で簡単に実装しました。

公開リンク
📱 Cal Food AI アプリをダウンロード：

iOS: https://apps.apple.com/us/app/cal-food-ai/id6744561874?platform=iphone

Android: https://play.google.com/store/apps/details?id=com.sildeswj.calfoodai

おわりに
「写真でカロリー管理」というコンセプトに興味のある方、ぜひ試してみてください！
技術的な質問やフィードバックも歓迎です 🙌

使用タグの例（投稿時に追加してください）
#AI

#ReactNative

#Gemini

#NestJS

#GCP

#健康

#カロリー管理
一撃作成したアラームアプリをChatGPTで機能拡張

前回はChatGPTでアラームアプリを一撃作成してみました。
予想に反して実用可能なアプリが作れたのは驚きです。
環境さえ整っていれば、ある程度のアプリは簡単に作れるので良いですね。

前回は音声でお知らせはしてくれなかったので、
ChatGPTさんにまたお願いしてみました。

プロンプトとしては
前回作成したコードを貼り付けて

```
上記のコードは指定した時間にアラームを鳴らして、自動的にスヌーズするPythonのコードです。

時間指定の画面に件名を入力するテキストインプットボックスを追加して
アラームが鳴った際に表示するようにしてください。

また、音声で「○○の時間になりました！」と○○のところに件名を入れてしゃべらせてください。
```
と入力してあげるだけ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880604/7ba7bc6f-559f-4a60-b5f4-25d427269ea5.png)

音声の読み上げにはpyttsx3を使用する用です。

調べてみると、

"pyttsx3は、Pythonでテキストを音声に変換するためのライブラリです。オープンソースで、Windows、macOS、Linuxなどのクロスプラットフォームで動作します。SAPI5 (Windows)、NSSpeechSynthesizer (macOS)、eSpeak (Linux)などのOSネイティブの音声合成エンジンを利用しており、オフラインで利用できるのが特徴です"

とのことで、問題ないようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880604/219f8eeb-a444-4b81-9313-41d4f4122a8c.png)
起動してみると、件名入力が出来るようになっていて、

時間になると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3880604/09367a23-dfd3-41ce-8133-d05d5dec7cff.png)
ちゃんと件名を入れて音声でお知らせしてくれました。
見切れているのはご愛敬。
このくらいは自分で修正してもいいですが
このままChatGPTと会話して完成度を上げていくのもいいと思います。
Lofree Flow Windows/Mac切り替え

Fn + M でMac用設定に
Fn + N でWindows用設定に切り替わる。

OSに適した方にしないと、Command+Cを押しているのにコピーできない！という事態になる。

ユーザーマニュアル
https://cdn.shopify.com/s/files/1/0692/4786/0967/files/flow100.pdf?v=1730254363
okanohara氏の伝説のprogramを発掘したので紹介

今回は遥か昔に失われた化石programを紹介します。これはかつてDO++というweb siteで公開されていたもので、最新版は2004/11/28です。
時は流れ2010年代初頭にsite消滅。[web archive](https://web.archive.org/web/20050121045908/http://homepage3.nifty.com/DO/sp.htm)でもprogramは入手不能のようです。
**そんなどうでもいいかもしれない歴史的背景はさておき**、本題にすり替えていきます。

## 現在の入手先
 [執筆者のgithub](https://github.com/da0ka/sp)
ただし、原作者も示唆している通り、bugがあります。**修正して頂ける方は大歓迎**

## 概要
### SP partial decodable compression
SPはStatic PPMを用いたData圧縮programです。従来のData圧縮法と比較し次の特徴があります。
* 全体を復元せずに**任意の部分のみを復元可能**
* 大きいfileに対して圧縮率はbzip2と同程度。小さいfileではgzipと同程度
* 復元処理の計算量、領域量は従来の高圧縮率の手法(BWTやPPM)と比較して小さい

## 問題点と対策
非歪みData圧縮法として主流の一角を成している PPM法は、全て動的、つまりDataを調べていくとともに圧縮に用いられるmodelも変わっていくものである。
それに対し静的PPM法は、最初にDataを調査し、model化をした後にそのmodelを圧縮されたDataと一緒に出力し、Dataを圧縮、復元する際には同じmodelを用いてPPMを行うというものである。
この静的PPM法という技法がなぜ今まで用いられなかったかというと、modelを出力すると、この部分が非常に大きくなるためと考えられる。

例として、静的 Order-2 PPM を考えると、この場合のmodel化は、ある文字が出現した際に、次にどのような文字がでてくるかという確率構造を調べるというものである。

これを通常の文字で考えた場合 256 の文字それぞれの次に 256 種類の文字が出現する可能性があるためこれを全て出力するには 256 x 256 個の確率情報が必要である。これと同様に OrderN であると、最悪 256 の n 乗個の確率情報が必要であり、このmodelを出力しようとすると非常に大きなoverheadとなる。そのため今までPPMというのは動的であるというのが主流であった。

model化したDataを効率よく出力する方法がある。これは、文字の出現確率と出現順位は反比例するという [Zipfの法則](https://ja.wikipedia.org/wiki/%E3%82%B8%E3%83%83%E3%83%97%E3%81%AE%E6%B3%95%E5%89%87)に基づいており、確率情報を最小二乗法で近似し、関数で出力するというものである。
```plain:Data例
abababacacadad
```
一例として上述のDataの場合、a の次に b が 3/7、cが 2/7、d が 2/7 の確率で出現するという情報がmodel化の際に必要である。

そこで、文字の出現確率の対数をとり、これを最小二乗法で近似し、この傾き、切片の情報、そして文字の順番を出力する。この際に必要なのは文字の順番、傾き、切片だけである。実際にこの考えを用いた圧縮programを作ってみたところ非常に良い結果がみられた 。Order3 の静的 PPM 法で、LHA や ZIP に匹敵する性能を見せている。
## 任意位置からの復元方法
一定間隔置きに前のDataとの依存関係が無いData圧縮をし、その位置をindex情報として保持しておく。復元する時は、復元したい場所の直前の、依存関係が無いDataまでindexで移動し、そこから復元する。
## 余談
なぜ今更こんな化石を掘り起こしたかと言うと、約15年前に死亡したPCから奇跡的にDataを取り出せたからです。
それはともかく静的PPMの例は1993?、1997年に既に登場している模様。[その実装がこれ](http://www.compression.ru/compression.ru/download/sources/cm/ziganshin_cm.rar)。
全然登録できなかったApple Developer Programがあっさり通った件

# 結論
Apple Accountの氏名をローマ字に変えてから購入処理を行ったら、1時間半くらいで「Apple Developer Programへようこそ」のメールが届いた。

# 詳細をもう少し
1. MacBook上でDeveloperアプリからApple Developerに登録しようとするも、「このapple accountでは、apple developerアプリからの登録をご利用いただけません。」と表示され登録ボタンが押せない
（2ファクタ認証はオンになっているのにアプリからは登録できなかった）
2. Apple Developer WEBサイトのDeveloper Program登録フォームに諸々英語で入力
3. 購入ページにクレカ情報などを入力して送信
4. 48時間以上経っても購入完了メールが届かない
5. Apple Developerサイト上でまたDeveloper Program購入処理→メールが届かない、を何度か繰り返す
6. 購入ページの下部にあるキャンセルボタンを押す
7. 「Your enrollment has been withdrawn.」のメールが来る
8. どこかのヘルプページに「アカウントの氏名はローマ字で」の記載を見つける
9. MacBookのシステム設定からApple Accountの氏名をローマ字に変更する
10. Developer Programの購入処理を再度行う
11. 1時間半ほどしたら「Apple Developer Programへようこそ」のメールが届き、証明書の作成などができるようになっていた

# その他情報
Apple Accountに登録してあるメールアドレスはGmailのもの。
他の記事だとGmailだとダメでiCloudのメールアドレスならいけた、という記述があったけれど、2025年4月ごろに試した限りでは、iCloudのメールアドレスではDeveloper Programには登録できない仕様になっていた。
理解しやすいコード1

エンジニア歴が6年になりましたが、改めてプログラミングについて学び直そうと思って、書籍で勉強しています。

書籍の1部で自分が大切だと思ったものをまとめております。
※少しずつ学んだ内容を個別に出していくつもりです。どのくらいのペースになるかわかりませんが...(;^_^A）

稚拙な内容になるかもしれませんが、さらっと読み流してもらえればと思います。

*******************************************************************
プログラミングを行う上で、意識するべきことは「理解のしやすさ」です。
理解しやすいコードを書いた時の利点として、以下のものが挙げられます。

利点
　・他の人やが見た時に、処理を理解するまでの時間が短くなる。
　　　⇒コードの変更、バグの発見、他のコードとの連携方法が理解できる
　　　　※時間をおいて自分で再度、確認した時も理解しやすい。

　・設計とテストのやりやすさに繋がる。
 
具体例として、JavaのIF分岐の書き方について以下のコードがあった場合、

例：IF分岐
　コード1：
　　　　　　return number == 0 ? sample1 * sample2 : sample1 + sample2;

　コード2：
　　　　　　if (number == 0) {
        
　　　　　　　return sample1 * sample2;
        
　　　　　　} else {

　　　　　　　return sample1 + sample2;
　　　　　　}

コード1と2は同じ処理内容で、簡潔に書いた場合と基本に沿って書いた場合で記載しています。
Java歴が長い人にとっては、一目でコード1と2の処理内容を一目で理解できる人は多いかもしれませんが、短い人にとっては、少し抵抗があるかもしれません。

ちなみにですが、自分は最初、一目で理解できず抵抗がありました...(;^_^A

もちろん、1クラスに実装するコード量が少なく、見やすいということもありますので、必ず、忠実に基本通りとしなければいけないというわけでもありません。
ただ、書くソースコードを理解しやすいものにしようと意識するだけで、バグが少なく、作業しやすいことにもつながるかと思います。

P.S.
初めて投稿しますが、投稿内容を理解しやすい様に書くのは意外と難しいですね(;^_^A
CloudWatch Logsの用語についてまとめてみた

## はじめに
CloudWatch LogsはAWSサービスの各種サービスで出力されるログを保存するサービスです。
S3と比べてコストは上がりますが、検索や管理が容易なのが特徴です。

## CloudWatch Logsの用語
CloudWatch Logs独自の用語で一般的には聞きなれない用語が多いため整理のためにまとめてみました。

AWS公式サイトには以下の用語が記載されています。
・ログクラス
・ログイベント
・ログストリーム
・ロググループ
・メトリクスフィルター
・サブスクリプションフィルター
・保持設定

### ログクラス
ログクラスは、アクセス頻度ごとにコストを最適化することができるオプションです。
ログクラスには以下の2つがあります。

| ログクラス | 説明 |
|:-|:-|
| 標準ログクラス | リアルタイムログやアクセスが頻繁に発生するログを格納するログクラスです。 |
| 低頻度アクセスログクラス |  アクセス頻度の低いログを格納するログクラスです。標準ログクラスよりもコストが低いです。|

### ログイベント
ログイベントは、モニタリングされているアプリケーションまたはリソースによって記録されたアクティビティのレコードです。

### ログストリーム
ログストリームは、同じソースを共有する一連のログイベントです。
ロググループ内でさらにソースごとのグルーピングした単位とお考えください。

### ロググループ
ロググループは、保持、監視、アクセス制御について同じ設定を共有するログストリームのグループを定義します。
ログストリームは必ず一つのロググループに属する必要があります。

### メトリクスフィルター
メトリクスフィルターは、ロググループに取り込まれたログイベントから特定の文字列などでフィルターをかけて抽出し、CloudWatch メトリクスのデータポイントとして利用できる機能です。
CloudWatch Alarm等と組み合わせてアクションを実行できます。

### サブスクリプションフィルター
サブスクリプションフィルターは、ロググループに取り込まれたログイベントから特定の文字列などでフィルターをかけて抽出し、他のAWSサービスに転送することができます。
メトリクスフィルターに比べて一つのロググループ当たりで設定できる上限が2つのため注意が必要です。

### 保持設定
保持設定は、CloudWatch Logs にログイベントを保持する期間を指定するための設定です。

## まとめ
今回はCloudWatch Logsの用語についてまとめました。
聞きなれない用語やなんとなく利用している画面の名称などの理解を深めることができました。

次回はEventBridgeについてまとめてみます。
Unity DevOps Build Automation + Build Profiles、AndroidのApplication IDはBuild Automation側の設定が優先される

2025年前半に、Unity DevOps Build Automation（以下、Build Automation）は、Build Profilesに対応しました。

https://qiita.com/RyotaMurohoshi/items/4f233cbb59f0d330d838

そんな「Build Automation + Build Profiles」の小ネタ。

2025年5月4日の時点では、「Build Automation」と「Build Profiles」両方でAndroidのApplication ID（Package Nameとも呼ばれる）で指定した場合、Build Automation側の設定が優先されるようです。

---

Build Automationでは、targetごとにApplication IDを上書きできます。

1. Build Automationの対象プロジェクトをブラウザで開く
2. Configurationsを選択
3. 変更したいtargetを選んで鉛筆アイコンをクリック
4. Basic Settingsタブを開く
5. Credentialssセクション中、Bundle IDに「Application IDとして設定・上書きしたい文字列」を入力

のような手順で、Application IDを上書きできます。

![スクリーンショット 2025-05-04 21.58.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/bb60d5c4-c3ef-49f2-890d-230b8e05097b.png)

---

Build Profilesも、Application IDをProfileごとに上書きすることができます。


Unityプロジェクト中、対象のBuild Profilesのインスペクターで、Player SettingsのOverridesを開きます。

![スクリーンショット 2025-05-04 21.20.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/8eb2bbc3-d553-4a1a-911e-7d32cfc876fe.png)

Identificationセクションの「Override Default Package Name」にチェックを入れ、Package Nameのエディットテキストに上書きしたい文字列で指定します。

![スクリーンショット 2025-05-04 21.22.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/f0df3903-210e-4702-adff-6a86c9c1926a.png)

---

このように、「Build Automation」と「Build Profiles」両方でAndroidのApplication ID（Package Nameとも呼ばれる）を指定できます。もし異なる文字列でそれぞれApplication IDを指定した場合、Build Automation側の設定が優先されるようです。（2025年5月4日時点）

---

今の「Build Automationが優先される仕様」だと、「あれ、Build Profileで設定したApplication IDにならない！？」という事故が発生しそうですね。

個人的には、Build AutomationでBuild Profilesを使っている場合は、

* Build Automation側で、AndroidのApplication ID指定・上書きできない
* 該当のエディットテキストがdisabledになる
* Application IDは、Build Profiles側で指定したものになる

という仕様だと嬉しいなと思っています。


---

ちなみに、「Scenes Path」はBuild AutomationでBuild Profilesを使っている状態だと


> This filed is disabled because a Build Profile path has been specified.

という注意書きが出て、Build Automation側で「Scenes Path」を指定することはできません。

![スクリーンショット 2025-05-04 22.12.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/ab684715-df9f-42f4-af23-f3ee777513bc.png)
sysモジュールの基本的な使い方

## はじめに

プログラムを作成する課題でsysモジュールを利用したので、基本的な使い方を整理したいと思います。



## sysモジュールとは

Pythonに標準で組み込まれている標準ライブラリです。



公式Docsによると、以下のような説明です。

> This module provides access to some variables used or maintained by the interpreter and to functions that interact strongly with the interpreter. It is always available. Unless explicitly noted otherwise, all variables are read-only.
   
https://docs.python.org/ja/3/library/sys.html

インタプリタで使用・保持されている変数を使うことができたり、インタプリタとの相互作用が強い関数を利用することができたりするモジュールのようです。



とこれだけ見てもよくわかりませんね。  
では、具体的にどのようなことができるのでしょうか？



以下のパラメータや関数を例に挙げて説明していきます。  

- sys.argv

- sys.exit(\[arg\])

- sys.path

## sysモジュールの利用方法

その前に、sysモジュールをスクリプトファイル上で利用できるようにimportしておきます。



標準ライブラリと聞くと、組み込み関数のprint文のようにimportしなくても使えそうな気がしますが、importが必要です。



```python
import sys
```

とすることでsysモジュールを利用できるようになります。

## sys.argv

コマンドラインに入力した引数はインタプリタが受け取り、sys.argvに格納されます。  

sys.argvの中身は以下のように、文字列のリストとして受け取ります。

```python
python example.py --hoge hoge
```

```python
['example.py', '--hoge', 'hoge'] # 出力結果
```

https://docs.python.org/ja/3/library/sys.html#sys.argv

## sys.exit(\[arg\])

プログラムを終了させることができます。  

引数のargには終了コードが入り、整数を入れることができます。



指定なし、あるいはNoneを指定すると0（正常終了）を返します。
終了コードは一般的には0\~127まであるそうですが、0から2だけ覚えておくのが良さそうです。




| 終了コード | 意味 | 
|---|---|
| 0 | 正常終了 | 
| 1 | 汎用的なエラー | 
| 2 | 構文エラー | 



また、sys.exitは整数以外にもオブジェクトを指定することができます。

例えば以下のようにエラーメッセージを指定することで、エラーメッセージを出力させつつプログラムを終了させることができます。

```python
sys.exit("This is error message!")
```

### 余談

sys.exit()ではなく、exit()がプログラム中に使われていたことを見たことがありました。
ざっと調べた限り、どちらもSystemExitを送出するのでほぼ同じ挙動だと思います。

公式Docsによると、exit()はプログラム中に記述するべきでなく、対話シェルで使うように！とのことです。


https://docs.python.org/ja/3/library/sys.html#sys.exit

## sys.path

sys.pathは文字列のリストです。  

どんな文字列からなるリストかというと、importされたときに、モジュールを検索するファイルパスが格納されているリストです。



リストなので、ファイルパスを追加したいときは、`sys.path.append` で追加可能です。



モジュールがimportできない場合は、このsys.pathを確認してみましょう。



https://docs.python.org/ja/3/library/sys.html#sys.path

## 終わりに

今回はsysモジュールの基本的な使い方をまとめました。

これ以外にも当然多くの機能がsysモジュールにはあります。



どんなパラメータが入っていて、どんな関数を利用できるのか？

どういうことができるモジュールなのか？

これらのことを理解しておくと、プログラムを作成するときにどのモジュールを使うべきか？の検討がつきやすくなると思います。



今後、sysモジュールに限らず、プログラム中で利用していくモジュールがどんな機能を提供してくれるのか？は頭に入れていきたいと思います。
8x8を2倍角に変換して遊ぶ(ビット操作



いろいろ、注意
----

- UNOでの予定は、未定


プログラム
----

オンラインコンパイラ　paiza

```c++

#include <iostream>
using namespace std;
int main(void){
    // Your code here!

    unsigned char font[] = {
        0x80,
        0x40,
        0x20,
        0x10,
        
        0x08,
        0x04,
        0x02,
        0x01
    };

    unsigned char font2[16*2];

    for(int i=0;i<8;i++){
    
        int s = 0;
        int al = font[i];
        s = s |(0b1000000000000000 & (al<<8));
        s = s |(0b0010000000000000 & (al<<7));
        s = s |(0b0000100000000000 & (al<<6));
        s = s |(0b0000001000000000 & (al<<5));
        s = s |(0b0000000010000000 & (al<<4));
        s = s |(0b0000000000100000 & (al<<3));
        s = s |(0b0000000000001000 & (al<<2));
        s = s |(0b0000000000000010 & (al<<1));
        s = s | (s>>1);
        
        
        font2[i*4+0] = s >> 8; 
        font2[i*4+1] = s & 0xff; 
        font2[i*4+2] = font2[i*4+0]; 
        font2[i*4+3] = font2[i*4+1]; 

        printf("[%02x],[%02x]\n",font2[i*4+0],font2[i*4+1]);
        printf("[%02x],[%02x]\n",font2[i*4+2],font2[i*4+3]);

    }//for
    
}


```


```

[c0],[00]
[c0],[00]
[30],[00]
[30],[00]
[0c],[00]
[0c],[00]
[03],[00]
[03],[00]
[00],[c0]
[00],[c0]
[00],[30]
[00],[30]
[00],[0c]
[00],[0c]
[00],[03]
[00],[03]

```
「ポエム」って言うな：軽い記事こそ大事だからこそ

Qiitaではよく「#ポエム」というタグが使われる。  
その多くは、以下のような意味合いで使われていると思う。

- 技術的な検証は薄い
- コードは書いてない
- 自分の思いや葛藤を書いている
- つまり「お気持ち記事」

書いている本人も「ただのポエムですけど…」と前置きしたりする。

でも、**ちょっと待ってほしい。**

---

## 書いてくれて、ありがとう。

まず言いたいのはこれだ。

> **検証が浅くてもいい。思いつきでもいい。書いてくれて、ありがとう。**

Qiitaは技術ブログであると同時に、「技術を学び合う場」だ。  
だからこそ、誰かの思考の過程、迷い、手がかりが共有されることには大きな意味がある。

すべての記事が完璧なコードでなければならないわけではない。  
「うまくいかないんだけど」「こう思ったんだけど」も大切な知見だ。

---

## それでも「ポエム」って言うのは、少し切ない

私は詩が好きだ。短歌が好きだ。

詩とは、思考や感情を削ぎ落とした表現。  
短歌は、31音に世界を詰め込む、精緻で濃密な表現だ。

そんな「ポエム」という言葉を、「なんか浅い記事」という意味で使ってしまうのは、  
**詩や感情を軽く見る態度に繋がってしまわないか？**

---

## 技術に厳しい人ほど、なぜ“感情”にだけは甘いのか？

技術の世界は厳密だ。

- バージョン違いがあれば即ツッコミ
- 間違ったコードは的確に指摘
- 「これは本当に動くのか？」という問いには厳しい

それなのに、「これは感情の話だから」として“ポエム”というラベルを貼って笑って済ませる。

でもそれって、**「感情や思考の試行錯誤」だけを雑に扱ってしまっていないか？**

---

## 名前を変えよう。「ポエム」じゃなくて。

思考や感情の共有は尊い。ならば、もっと誠実な名前で呼びたい。

| 呼び方 | 特徴 | 備考 |
|--------|------|------|
| **技術雑感** | 感想・迷い・考えの途中を書いたときに | 真面目さがある |
| **技術ノート** | 試行錯誤や中間報告として | Jupyter的な意味合い |
| **開発ログ** | 手がかり・反省点・メモなど | 記録であることを強調 |
| **メモ** | 発展途中の思考を共有する | 未完成を許容する言葉 |

---

## 「軽さ」を否定しない。でも「軽視」はしない。

Qiitaには、もっと「未完成な記事」や「気づきの途中」を書いてほしい。  
でも、だからこそ「軽い記事」を“軽視”するような言葉は使いたくない。

誰かの思考や試行錯誤を「#ポエム」で矮小化せず、  
もっと自然に、もっと誠実に受け止めたい。


---

## まとめ

- 「ポエム」というタグは感情や未完成な記事を軽視しかねない
- 思考の途中やお気持ちの共有も、大切な技術的アウトプット
- 書いてくれた人へのリスペクトを込めて、呼び方を変えよう
- Qiitaは、完璧なコードだけじゃなく、“途中”も大切にする場所であってほしい

---

**あなたの「未完成」を、誰かが待っているかもしれない。**

だから、#ポエムではなく、#メモ くらいで投稿してみてほしい。
【WordPress 6.8】ハッシュアルゴリズム変更の影響とダウングレード時の注意点

# はじめに

WordPress 6.8より、「パスワードをハッシュ化するアルゴリズムが変更される」とのアナウンスがありました。 
この変更により、どのような影響が出るのかを調査しました。  
ざっくりした結論を先にお伝えすると、ダウングレードした際にパスワードを再設定しない限り、ログインできなくなります。

# 変更について

## 概要

セキュリティ強化のため、ハッシュアルゴリズムがphpassからbcryptに変更されます。

## 変更タイミング

アップグレードが完了した後の初回ログイン時に、ハッシュアルゴリズムの変更が行われます。

## 変更の影響

ハッシュアルゴリズムがbcryptに変更された状態で、WordPress 6.8から6.7へダウングレードした場合、ログインできなくなります。

# ダウングレードした際のログイン方法

ログイン画面の「パスワードをお忘れですか？」をクリックして、パスワードを再設定してください。  
※ テーブルを直接書き換える方法もありますが、ここでは簡単で確実な方法のみを紹介しています。

# 余談

メジャーバージョンアップを行う際は、フルバックアップを取ってから手動で実施することで、この手のトラブルに巻き込まれにくくなります。  
また、後から戻そうとすると大変な作業になるため、メジャーバージョンアップ直後にテストを行い、可能であればしばらく様子を見てからコンテンツを更新する運用が望ましいと思われます。

# さいごに

本記事をまとめると、以下の通りです。

1. アップグレード後の初回ログイン時に、自動でphpassからbcryptにハッシュアルゴリズムが変更されます。
2. ハッシュアルゴリズムがbcryptに変更された状態で、ダウングレードすると、ログインができなくなります。
3. ログインするためには、パスワードの再設定が必要です。

# 参考文献
https://wordpress.org/download/releases/6-8/

https://151en.com/wordpress/20250416/12208/

https://elearn.jp/wpman/column/c20250414_01.html

https://elearn.jp/wpman/function/wp_hash_password.html
LLMをAndorid純正ターミナルで完全ローカルで動かす

最近Andoridで純正のLinuxターミナルが使えるようになりましたね。(現時点ではPixel限定らしいですけど。)

ということはLlama.cppも動くはずなのでやってみました。

## 実行環境

- Pixel 6a
- Android 15
- モデル: unsloth/gemma-3-1b-it-GGUF/gemma-3-1b-it-UD-IQ1_S.gguf

## 実行コマンド

Andoridからコマンドを打つことになると思うので、コピペしやすくコマンド1個1個書いていきます。

なお、AndoridでLinuxターミナルを使えるようにするまでは他の人が解説していると思うので割愛します。

### aptの更新

```sh
sudo apt update
```

```sh
sudo apt upgrade -y
```

### パッケージのインストール

```sh
sudo apt install -y wget git cmake g++ libcurl4-openssl-dev
```

### Llama.cppのインストール

```sh
git clone https://github.com/ggml-org/llama.cpp
```

```sh
cd llama.cpp
```

```Sh
cmake -B build
```

```sh
cmake --build build --config Release
```

```sh
cd ..
```

### モデルのダウンロード

今回はunslothが量子化したGemma-3-1b-itを使ってみます。軽いので。

```sh
wget https://huggingface.co/unsloth/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-UD-IQ1_S.gguf
```

### モデルの起動

```sh
./llama.cpp/build/bin/llama-server -m gemma-3-1b-it-UD-IQ1_S.gguf
```

**実行したあとに8080番ポートの開放の通知があるので開放する。**

### 推論の実行

ブラウザアプリを起動して、以下のアドレスへアクセスする。

```
http://localhost:8080
```

開いたページでこんな感じでモデルとチャットができるようになります。

![Screenshot_20250504-210133.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568254/624a817b-5c01-4fbf-adec-efe189f73ae3.png)

## 結論

めちゃくちゃ遅いですし、応答内容もこんな感じですので使い物にならないですね。
GitHubとローカルプロジェクトを連携する方法

# はじめに

最近プログラミング学習を始めた知人から「GitHubのリポジトリに登録できない」と相談されました。
私も最初は躓いた部分だったので、その時のことを思い出しながらGitHubにローカルプロジェクトをアップロードする方法をQiitaにまとめてみました。

この記事では、まだGitやGitHubに慣れていない方に向けて、ステップバイステップで分かりやすく説明していきます。

# ローカルからの作成（おすすめ✨）

### ローカル環境にプロジェクト作成

既に作ったプロジェクトのフォルダがある状態を前提とします。

### GitHubで新しいリポジトリを作成

右上のアイコンから「Your repositories」->「New」を選択します。

![git_1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920283/9265c69f-7094-4c48-a863-faf94f7c9df4.png)

「New」を選択
![git_2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920283/1e56e43d-00d4-4f07-b7f4-1e9cb4877489.png)

リポジトリ名を入力します。
必ずプロジェクト名と同じ名前にしてください。
プロジェクト名をカレントディレクトリの状態で実行することも必須です。

下の方に表示されている
`…or create a new repository on the command line`
のコマンドをそのまま実行してOKです。

```
echo "# [project名]" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:[your-username]/[project名].git
git push -u origin main
```

1行ずつ何が書いてあるのか見てみましょう。

- READMEを作る
```
echo "# [project名]" >> README.md
```

README.md というファイルを作り、その中に `# [project名] ` を記述します。
これはプロジェクトの説明を書くファイルです。

- Git管理を開始
```
git init
```
このプロジェクトフォルダを Git で管理できるようにします。
実行すると `.git` という隠しフォルダができて、Gitが変更を追跡できるようになります。

- ファイルをステージングする
```
git add README.md
```
`README.md`をGit対象に追加している。

※先にプロジェクトを作成していてプロジェクトすべてをリポジトリに連携したい場合は `git add README.md` ではなく以下のコマンドが便利です。
個人的にはいつもこっち！！

```
Git add .
```
現在のフォルダ内のすべての新規ファイル・変更されたファイルをステージングします。

```
git commit -m "first commit"
```
追加したファイルをスナップショットとして保存（コミット）します。
-m はメッセージ（コメント）をつけるオプションです。

```
git remote add origin git@github.com:[your-username]/[project名].git
```
GitHub上のリポジトリと、このローカルのGitを紐づけます。
※ [your-username] や [project名] は自分のものに書き換えてくださいね。

```
git push -u origin main
```
ローカルの main ブランチを GitHub にアップロード（push）します。
-u をつけることで、次回からは git push だけでOKになります！

GitHubをリロードすると、リポジトリが完成します🙌

### エラーが出たら・・・

初めてGitに登録する時よく出るエラーです。

- ユーザー名とメールアドレスを登録してねエラー
```
Author identity unknown
```
Gitのユーザー情報（名前・メールアドレス）をまだ設定していないから出るエラーです。

1回だけ設定すればOK！
```
git config --global user.name "[your-username]"
git config --global user.email "[your-email]"
```

設定が反映されたか確認

```
git config --list
```


user.nameとuser.emailが登録通りに表示されていればOK
```
user.name=your-username
user.email=your-email@example.com
```

- SSH設定してないよエラー

```
Permission denied (publickey).
```

もしSSH設定に関してエラーが発生した場合は、[GitHubで ‘Permission denied’ エラーが出たら？SSHキーの作成と設定方法](https://qiita.com/yochan__/items/d24267483b2a4e75ea2d)を参考にしてください。

# 最後に

GitHubを使い始めたばかりの方にとって、最初の一歩は少し敷居が高いかもしれませんが、慣れてしまえばとても便利なツールです。
エラーが出ても焦らずに、少しずつ解決していくことが大事です。
この記事が、GitHubの使い方を学ぶ上での手助けになれば嬉しいです。
これからも、どんどんGitHubを活用していきましょう！
GitHubで ‘Permission denied’ エラーが出たら？SSHキーの作成と設定方法

# はじめに

GitHubでcloneしようとしたら、
`Permission denied (publickey)` という謎のエラーが出た…。
最初すごく戸惑った経験があるので「SSHキーの作成方法」と「GitHubへの登録方法」をMacユーザーの私が、Windows環境で優しく解説していきます。

特に新しいPCに変えた時や初めてSH接続するときに役立つ内容です。

## 

こんなエラーです。
```
// 公開鍵認証失敗
git@github.com: Permission denied (publickey).

// リポジトリにアクセスできない
fatal: Could not read from remote repository.

// アクセス権が正しいか、リポジトリが存在するか確認してね
Please make sure you have the correct access rights and the repository exists.
```


**Permission denied (publickey).**
ここが一番重要なポイントで、「公開鍵認証が失敗しました」という意味です。
GitHub 側は「この接続元のSSH鍵、知らないよ？」という反応をしている状態ですね。


## 既にSSHキーがあるか確認する

```
ls ~/.ssh
```

出力例
- `id_rsa`: 秘密鍵（他人に見せない）
- `id_rsa.pub`: 公開鍵（Githubに登録する）

## SSHキーを作成する

"your_email@example.com" は GitHub に登録しているメールアドレス

```
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```

Enterキーで進む
```
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\Hoge/.ssh/id_rsa): 
```

Enterキーで進む
```
Enter passphrase (empty for no passphrase): 
```

Enterキーで進む
```
Enter same passphrase again: 
```

成功すると2つのファイルが作成される
- C:\Users\Hoge\.ssh\id_rsa

- C:\Users\Hoge\.ssh\id_rsa.pub

```
Your identification has been saved in C:\Users\Hoge/.ssh/id_rsa
Your public key has been saved in C:\Users\Hoge/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:uUkIqPT6a9uCpZEDbxACNmcdER0ba1ebCxjZ9BUWaR0 your_email@example.com
The key's randomart image is:
+---[RSA 4096]----+
|oo o.+=+=. . ==E.|
|+ +. . o*.o =o . |
|.o. .  = o +.    |
|+..  ...... .    |
|oo..  . S  .     |
| ++.   . o       |
| o*     o        |
| o.o.            |
|  .++.           |
+----[SHA256]-----+
```

## 正常に鍵が作成できたか確認する

```
ls ~/.ssh
```

こういうのが出力されればOK

```
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        2025/04/09      8:45           3389 id_rsa
-a----        2025/04/09      8:45            751 id_rsa.pub
-a----        2025/04/08      8:30             92 known_hosts
```



## 公開鍵（.pub）をGitHubに登録する

以下のコマンドで出力された文字列全体をコピー

- Mac（またはWSL）の場合
```
cat ~/.ssh/id_rsa.pub
```

- Windowsの場合
```
 type $env:USERPROFILE\.ssh\id_rsa.pub
```

### GitHubに公開鍵を追加

GitHubにログイン

`Settings`を選択

![DF1B28D3-75E0-4894-8500-A05413530155_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920283/88210e42-87d8-4b78-8981-a4139ba429d4.jpeg)



左側メニューの`SSH and GPG keys`をクリック

![DAA27DFE-C437-4FA8-A2E4-2CBF80FDDECD_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920283/80d19d78-e1b1-4e14-b42e-a4fadfcc93a1.jpeg)



`New SSH key`をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920283/e21b892c-23cc-4654-98f0-8845ffddc5cb.png)

Title：任意のタイトル
Key：コピーした公開鍵を貼り付ける

`Add SSH key`を押下

これでSSHの設定は完了です✨

### 接続テスト
```
ssh -T git@github.com
```

成功時のメッセージ
```
Hi yourusername! You've successfully authenticated, but GitHub does not provide shell access.
```

# 最後に

GitHubはつまずきやすいですが、少しずつ慣れていけば大丈夫。

この記事の通りにリポジトリを作ってみましょう！
[GitHubとローカルプロジェクトを連携する方法](https://qiita.com/yochan__/items/cad2fa17c88d2144b426)
ローカルで ES Modules を読み込むと CORS エラーになる原因と VSCode Live Server での解決手順

## 1. 経緯  
ローカルの HTML で ES Modules を読み込もうとしたところ、次のエラーが発生しました。

```
Access to script at 'file:///…/js/index.js' from origin 'null' 
has been blocked by CORS policy
GET file:///…/js/index.js net::ERR_FAILED
```

## 2. 症状と原因

| 症状 | 主な原因 |
|------|----------|
| CORS エラー（`origin 'null'`） | `file://` 直読みで **Origin が `null`** になる |


> **ポイント**  
> ES Modules は HTTP/HTTPS で配信しなければならず、ファイル直読みはブロックされます。

---

## 3. 解決策：VSCode Live Server を使う

1. **Live Server 拡張をインストール**  
   - VSCode 左側の拡張アイコン →「Live Server」を検索 → インストール

2. **サーバーを起動**  
   - `index.html` を右クリック → **Open with Live Server**  
   - ブラウザが `http://127.0.0.1:5500` などで自動起動



## 4. まとめ
ES Modules を読み込むには

\<script type="module"> が必須

HTTP/HTTPS 経由で配信する必要がある

ローカル開発では VSCode Live Server を使うのが最も簡単。

ファイル直読み (file://) は Origin が null になるため CORS でブロックされる。

## 補足：用語解説
### ES
ECMAScript の略称。JavaScript の正式仕様名です。

### Origin
URL の スキーム（http/https）＋ホスト＋ポート の組み合わせを指す言葉で、ブラウザは「同じ Origin から読み込まれたかどうか」でアクセス制限（CORS）を行います。

例: https://example.com:443

file:// で開くファイルは Origin が null になるため、別ファイルをモジュールとして読み込もうとするとブロックされます。
Linucレベル１勉強メモ　＃１５

＃ 第一章　Linuxのインストールと仮想マシン・コンテナの利用

練習問題1.15
ネットワーク経由でリモートホストのXクライアントがローカルホストのXサーバーを利用したい場合、リモートホストで設定すべき環境変数を記述してください。

__________

（解答） DISPLAY

（解説）
リモートホストのXクライアントプログラムがローカルホストのXサーバーを利用する場合、Xクライアントは出力先のXサーバーを知る必要があります。その設定は環境変数DISPLAYを利用します。DISPLAY変数には「localpc:0」のような値が設定されます。

ネットワーク経由でのXの利用
X Window systemはネットワーク経由で利用できます。つまり、Xサーバーが稼働しているのとは別のコンピュータで動作しているXクライアントを表示し、操作するといったことが可能です。

（わからない単語解説）
* 環境変数<br>プログラムが動作する上で必要な設定情報を、オペレーティングシステムが管理する変数です。
2025年に追加されたJavaScriptのPromise.try機能：エラー処理をもっと簡単に！

最近はES2025の文法を色々と見ているものです。
JSが今後目指してることと、どこに活用できるのか考えることで色々と勉強になりますね~

↓前回の記事

https://qiita.com/Procrustes5/items/30e04b4c8fcf902db46c

今回は`Promise.try`という新しい機能についてみていきます。同期と非同期のエラー処理を統一する画期的な機能です！

## 従来の面倒なエラー処理

これまで、JavaScriptでエラー処理を書く時は同期処理と非同期処理で異なる方法を使う必要がありました。

### 同期処理のエラー処理
```javascript
// データをパースする同期処理
try {
  const data = JSON.parse(jsonText);
  console.log(data);
} catch (error) {
  console.error('パースエラー:', error);
}
```
### 非同期処理のエラー処理
```javascript
// APIからデータを取得する非同期処理
fetch('/api/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('取得エラー:', error));
```

## 「この関数、同期？非同期？」問題

実際の開発では、関数が同期的に動くか非同期的に動くかわからないケースがよくあります。
違ったやり方を取ろうとも、判断ができないときは困りますよね。

例えば、キャッシュ機能を持つデータ取得関数のことを考えてみましょう。
```javascript
function getUserData(userId) {
  // キャッシュにあれば即座に返す（同期的）
  if (cache.has(userId)) {
    return cache.get(userId);
  }
  
  // キャッシュになければAPIから取得（非同期的）
  return fetch(`/api/users/${userId}`)
    .then((res) =>  {
      return res.json();
    });
}
```

この関数を使う際、毎回「try/catchで囲むべき？それともthen/catchを使うべき？」と悩む必要がありました。

これまでの解決策は、以下のように常にPromiseを返すように統一することでした。
```javascript
function getUserData(userId) {
  if (cache.has(userId)) {
    // 同期的な値もPromiseでラップ
    return Promise.resolve(cache.get(userId));
  }
  
  return fetch(`/api/users/${userId}`)
    .then((res) =>  {
      return res.json();
    });
}
```

## Promise.tryはシンプル

`Promise.try`を使えば、この問題が解決できます。

```javascript
Promise.try(() => getUserData(123))
  .then(data => {
    console.log('ユーザーデータ:', data);
  })
  .catch(error => {
    console.error('エラー発生:', error);
  });
```

`Promise.try`の便利な点は、
- 関数が同期でも非同期でも、常にPromiseとして扱える
- エラー処理が`.catch`に統一される
- コードの見通しが良くなる

読みやすすぎる！

## 実践的な使用例

### 設定ファイルの読み込み
```javascript
// 同期的な読み込みかもしれないし、非同期的な読み込みかもしれない
Promise.try(() => loadConfig())
  .then(config => {
    // 設定を使用
    initializeApp(config);
  })
  .catch(error => {
    console.error('設定の読み込みに失敗:', error);
    // デフォルト設定を使用
    initializeApp(defaultConfig);
  });
```

### フォームの送信処理
```javascript
// バリデーションは同期的、APIコールは非同期的
Promise.try(() => {
  validateForm(formData);  // エラーを投げる可能性がある同期処理
  return submitToAPI(formData);  // 非同期処理
})
.then(result => {
  showSuccessMessage('送信成功');
})
.catch(error => {
  showErrorMessage('エラー: ' + error.message);
});
```

## Promiseを普段使わない人にも

「Promiseは難しそう」と思っている方も、`Promise.try`は気軽に使えます。

以下のような「try/catchのPromise版」として捉えてみてください！
```javascript
// これまでのtry/catch
try {
  const result = someFunction();
  // 成功時の処理
} catch (error) {
  // エラー時の処理
}

// Promise.tryを使った場合
Promise.try(() => someFunction())
  .then(result => {
    // 成功時の処理
  })
  .catch(error => {
    // エラー時の処理
  });
```

## まとめ

私も普段あまりPromiseを頻繁に使っているわけではありませんでしたが、Promise.tryは気軽に使えるのでES2025が安定したらどんどん使っていきたいですね！
Atcoder(競技プログラミング) の学習記録作成

今日から競技プログラミングについてのまとめ記事をかいていきます。
Qiita、Atcoder ともに初心者ですが、
自身と同じ状況になった未来の学生のためにがんばって作成しまし

筆者
情報系3年
就活で競技プログラミングの実績が必要になった

投稿頻度
目標:週7
予想:週3

投稿内容
Atcoderの過去問について
pythonコードとその考え方
[VRChat] FaceEmoで表情作成・設定ツール

## ⭐️目的

- 表情改変
-


## ⭐️参考

https://metacul-frontier.com/?p=7278

https://vrnavi.jp/faceemo/

https://note.com/moegitsubasa/n/n46f161d02112

https://kohavrog.com/faceemo/

### ☂️公式

https://suzuryg.github.io/face-emo/ja/docs/tutorials/

https://booth.pm/ja/items/4915091

## ⭐️インストール

https://suzuryg.github.io/face-emo/ja/

![スクリーンショット 2025-05-04 19.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/b4f44d05-d8f8-45cd-8ff7-05cb4ec0c7ad.png)


## ⭐️使い方


![スクリーンショット 2025-05-04 19.49.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/a5d805a2-68a0-44d6-9aee-e062b8335bf6.png)

- ここからnew menuしてヒエラルキーに追加

![スクリーンショット 2025-05-04 19.59.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/3c1858a5-b067-4b2a-a5dc-de71e215a909.png)

- 対象となるアバターを選択してEmoをクリック

![スクリーンショット 2025-05-04 20.00.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/e8f79a05-845e-4b89-b765-1e9d6f94082e.png)

- ポップアップで管理画面が出てくる
- あとは適当に設定していく

## ⭐️指の指定例

- neutral デフォ
- Fist✊:
- Open🖐️:笑顔
- Point☝️:悲しげ
- Victory✌️:喜び
- Rock🤟:怒り
- Gun👉:煽り
- Thumbs👍:笑顔

など
指定プログラム実行

~~~
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' 指定プログラム実行
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Public Function F_Shell_OpenFile( _
        ByVal aFilePath As String, _
        ByVal aExePath As String, _
        Optional ByVal aExeArg As String = "", _
        Optional ByVal aWindowStyle As VbAppWinStyle = vbNormalFocus) As Boolean
    Dim wkRet As Boolean: wkRet = False
    Dim wkCmd As String
    
    '引数チェック
    If Dir(aFilePath) = "" Or Dir(aExePath) = "" Then
        Exit Function
    End If
    
    wkCmd = aExePath
    wkCmd = M_String.F_String_ReturnAdd(wkCmd, aExeArg, aDlmt:=" ")
    wkCmd = M_String.F_String_ReturnAdd(wkCmd, aFilePath, aDlmt:=" ")
    
    Shell wkCmd, aWindowStyle
    
    F_Shell_OpenFile = True
End Function
~~~
外部プログラム実行

~~~
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' 外部プログラム実行
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Public Function F_Shell_Run( _
        ByVal aCmd As String, _
        Optional ByVal aWindowStyle As Long = 0, _
        Optional ByVal aWaitOnReturn As Boolean = False) As Boolean
    Dim wkRet As Boolean: wkRet = False
    Dim wkRtn As String
    
    Dim wkShell As New WshShell
    Dim wkCmdRet As Integer
    
    '引数チェック
    If aCmd = "" Then
        Exit Function
    End If
    
    On Error GoTo PROC_ERROR
    'コマンド実行
    wkCmdRet = wkShell.Run(aCmd, WindowStyle:=aWindowStyle, WaitOnReturn:=aWaitOnReturn)
    If aWaitOnReturn = True Then
        '正常終了している場合は正常を返却
        If wkCmdRet = 0 Then
            wkRet = True
        End If
    Else
        '一旦正常とする
        wkRet = True
    End If
    On Error GoTo 0
    
PROC_ERROR:
    F_Shell_Run = wkRet
End Function
~~~
外部プログラム実行結果取得

~~~
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' 外部プログラム実行結果取得
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Public Function F_Shell_GetResult( _
        ByRef aRtn As String, _
        ByVal aCmd As String) As Boolean
    Dim wkRet As Boolean: wkRet = False
    Dim wkRtn As String
    
    Dim wkShell As New WshShell
    Dim wkExec As Object
    
    '引数チェック
    If aCmd = "" Then
        Exit Function
    End If
    
    On Error GoTo PROC_ERROR
    'コマンド実行
    Set wkExec = wkShell.Exec(aCmd)
    
    wkRtn = wkExec.StdOut.ReadAll
    On Error GoTo 0

    If wkRtn <> "" Then
        aRtn = wkRtn
        wkRet = True
    End If

PROC_ERROR:
    F_Shell_GetResult = wkRet
End Function
~~~
M_Shell：各種定義

~~~
'##############################################################################
' 外部プログラム処理
'##############################################################################
' 参照設定          |   Windows Script Host Object Model
'------------------------------------------------------------------------------
' 参照モジュール    |   M_String
'------------------------------------------------------------------------------
' 共通バージョン    |   ―
'------------------------------------------------------------------------------

'==============================================================================
' 公開定義
'==============================================================================

'==============================================================================
' 内部定義
'==============================================================================
~~~
エラー 「ERROR: 'OpenSSL.crypto' has no attribute 'sign'」の解決

`gcloud storage sign-url`を実行しようとしたところ、表題の通りのエラーが発生した。

## 解決方法

依存ライブラリの`pyOpenSSL`のバージョンを25.0.0から24.2.1にダウングレードする

`pip install pyOpenSSL==24.1.1`

## エラーの原因

`pyOpenSSL`の依存先`openSSL`v24.3.0でsignメソッドが削除されたため。

## 参考リンク

https://github.com/googleapis/google-api-python-client/issues/2554