Active StorageでアップロードしたファイルのURLを即返すときに気をつけること

(注記)これはだいぶ雑なまとめです。間違いあったら教えて下さい!

  • ActiveStorageでDiskServiceを利用している場合、URLのドメイン部分はリクエストからいい感じに生成される
  • ActiveStorage::SetCurrentというモジュールをコントローラにincludeするとbefore_actionでリクエストの情報をCurrentAttributeにアサインする
  • 開発環境だとActiveStorage::SetCurrentをincludeすれば問題ないんだけどテスト環境で問題になることがある
  • ActiveStorage::Current.host not set causing disk service to throw URI::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