(注記)これはだいぶ雑なまとめです。間違いあったら教えて下さい!
- 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?)には固定のデフォルト値のようなものが設定できるようになってこの手のハックは不要になるかもしれない