Logi Options+アプリケーションで次のように設定するといい感じになります
最近のsecret_key_baseの変遷についてのざっくりまとめ
開発環境、テスト環境のsecret_key_base
- Rails5.2から自動生成されるようになった
- Railsアプリケーション名をMD5したものを利用していた
- Add credentials using a generic EncryptedConfiguration class (#30067) · rails/rails@69f976b
- アプリケーション名から生成すると値が推測できてしまってセキュリティ的によろしくない、ということでRails6.0からは
SecureRandom.hex(64)
に変更された- 値は
tmp/development_secret.txt
に書き込むようになった - Fix possible dev mode RCE · rails/rails@4c74358
- 値は
- テスト環境でも使うので
tmp/development_secret.txt
という名前は良くない、ということでtmp/local_secret.txt
にリネームされた(Rails7.1.0.beta1) - Rails v7.2.0.beta1以降、Rails.application.secrets削除コミットの影響で、開発環境及びテスト環境のsecret_key_baseは
tmp/local_secret.txt
の値が決め打ちになっていた- 過去には
ENV["SECRET_KEY_BASE"]
やRails.application.credentials.secret_key_base
も使えていた - Use
secret_key_base
from ENV or credentials when present locally by p8 · Pull Request #53705 · rails/rails - Rails 8.0.2及び7.2.3(2025/01/27時点で未リリース)でバグフィックスが入り、
ENV["SECRET_KEY_BASE"]
やRails.application.credentials.secret_key_base
がまた使えるようになる
- 過去には
- Rails5.2から自動生成されるようになった
Rails7.1から、
rails assets:precompile
用のダミーsecret_key_baseの設定ができるようになった- デプロイ環境でassetsのビルドまで行う等、必ずしも
rails assets:precompile
をする環境にRAILS_MASTER_KEY
(つまりsecret_key_base)が設定されているとは限らないので、ワークアラウンドとしてENV["SECRET_KEY_BASE_DUMMY"]
があればSecureRandom.hex(64)
をsecret_key_base
として使うようになった - Allow assets:precompile to be run in a production build step without … · rails/rails@a3e392f
- デプロイ環境でassetsのビルドまで行う等、必ずしも
本番のsecret_key_base
Active StorageでアップロードしたファイルのURLを即返すときに気をつけること
(注記)これはだいぶ雑なまとめです。間違いあったら教えて下さい!
- ActiveStorageでDiskServiceを利用している場合、URLのドメイン部分はリクエストからいい感じに生成される
- ActiveStorage::SetCurrentというモジュールをコントローラにincludeするとbefore_actionでリクエストの情報をCurrentAttributeにアサインする
- 開発環境だと
ActiveStorage::SetCurrent
をincludeすれば問題ないんだけどテスト環境で問題になることがある ActiveStorage::Current.host
not set causing disk service to throwURI::InvalidURIError
· Issue #40855 · rails/rails- テスト環境(例: コントローラスペック)でアップロードしたファイルのURLを即返すようなケース
- テスト時に
user.save
→userの画像がアップロードされる→サムネイルを作るタイミングでActiveStorage::DiskControllerのshowアクションが実行される→Executorが実行される→CurrentAttributesの値のクリアが実行される→ActiveStorage::SetCurrentで設定したはずの値がクリアされてしまう→ファイルのurlを参照しようとしてエラーになる、という流れになるはず - これはテストが1スレッドで実行されているのが原因なので、複数スレッドな環境では起きないはず
- テスト時に
- 解決策としては、rails_helper.rbなどに↓を書く
Rails.application.executor.to_complete do ActiveStorage::Current.url_options = { host: 'http://example.com' } end
- もしくは開発環境及びテスト環境でもS3Serviceなどを使うようにして、DiskServiceを使うのをやめると良い
- 将来的(Rails8.1?)には固定のデフォルト値のようなものが設定できるようになってこの手のハックは不要になるかもしれない
rubymineでFind Actionしたいのにできないのを解決する方法
- rubymineのキーバインドにcmd+shift+aがfind action(アクションに絞り込んだ検索)として用意されている
- が、mac上で実際にそれを打つとなぜか次のようになる
- これは↓にある「ターミナルのmanページインデックスで検索」のキーバインドと競合しているから
- ↑のようにチェックを消すと良い
docker-compose コマンドとdocker composeコマンドは別物
- M1 macで
docker-compose up
するとなぜかexec /usr/local/bin/docker-entrypoint.sh: exec format error
- docker imageはintel用なのでそれが関連している
- と思って色々試したがなにも変わらず
- docker desktopのバージョンを4.31.0 -> 4.32.0に上げたら
docker-compose up
が失敗するようになり"docker-compose"コマンドを使っているのが良くないんじゃ?という事実に気づいた docker compose up
としたらうまくいきました- コマンド履歴で
docker-compose up
を実行していたのが良くなかったという話
E2Eテストでバリデーションを調整してタイムアウトを抑制する
- 関連: system specでNet::ReadTimeoutになったら - おもしろwebサービス開発日記チラシの裏
- やっぱりタイムアウトの時間を伸ばすのではなく、テスト側でバリデーションの条件を緩和してあげたほうがトータルのテスト実行時間が短くなっていいんじゃないか、と思って次のようにした
- (設定はpalkan/anyway_config: Configuration library for Ruby gems and applicationsを使っています)
class DailyReport < ApplicationRecord validates :body, presence: true, length: { maximum: -> { ValidationConfig.daily_report[:body][:maximum] } } end
around do |example| original = ValidationConfig.daily_report[:body][:maximum] ValidationConfig.daily_report[:body][:maximum] = 10 example.run ValidationConfig.daily_report[:body][:maximum] = original end
- rails5.2から、maximumにlambdaを渡して動的に条件を変えられるようになっている
- また、rails7.1からは引数なしのlambdaでも受け付けられるようになっている
flashメッセージが時々表示されないflakyテストを改善した話
Railsで
- cookie sessionを使っている
- 非同期でAPIをよく叩いている
という条件下で、例えば日報を投稿したあとに"投稿しました!"というflashメッセージを表示しているはずなのになぜか"投稿しました!"が表示されないという現象が時々起こっていました。
これは次のようなことが原因だと推測しています。
- 非同期API(例: 日報のプレビューを表示する)が実行される
- 日報投稿ボタンを押す
- 投稿が成功して日報詳細ページへのリダイレクト用のレスポンスが返される
- SetCookiesでflashメッセージを含んだcookie sessionが返される
- 非同期APIのレスポンスが返る
- SetCookiesでflashメッセージを含まないcookie sessionが返される
- 日報詳細ページへのリクエストが実行される
- このとき送信するCookieにはflashメッセージが含まれていないので"投稿しました!"は表示されない
長らくこの問題に悩まされていたのですが、API実行時は次のようにしてSetCookiesヘッダを返さないようにするという方法を思いついたので試してみました。おそらくこれで解決するはず。
class Api::BaseController < ApplicationController class NullCookieJar < ActionDispatch::Cookies::CookieJar def write(*) # nothing end end before_action :null_cookies def null_cookies request.cookie_jar = NullCookieJar.build(request, {}) end end