現象
Rails4/5/6に関する重大なSecurityFix / 2019年3月13日 01:49 - Qiita
を読んでRailsのバージョンを上げることにした
bundle update railsしたら依存関係にあるgemもバージョンが上がった。
その際に出たバグの中に、Sprocketsを3系にあげると、Production環境でRails.application.assetsが使えなくなるというのがあった
実際に出たエラー
undefined method '[]' for nil:NilClass
なお、Rails.application.assets["file_name"]はRails.application.assets.find_asset("file_name")のエイリアス
同様の現象についてのIssueは結構あるのだが、結局何をすればいいのかを調べるのに時間がかかったのでメモしておく
sprockets/UPGRADING.md at 3.x · rails/sprockets
Rails.application.assets is nil in production #237
Rails.application.assets returns nil on version 3.5.2 · Issue #294 · rails/sprockets-rails
解決策
以下の2つの方法があると思う
-
Rails.application.assets
のかわりにSprockets::Railtie.build_environment(Rails.application, true)
を使う -
assets.compile = true
を指定する
今回は1を採用した
2はrailsの公式サイトにパフォーマンスが悪くなるからやめろと書いてあったので見送った
アセットパイプライン - Rails ガイド
このモードはデフォルトよりもメモリを余分に消費し、パフォーマンスも落ちるためお勧めできません。
Sprockets::Railtie.build_environment(Rails.application, true)を使う
Rails.application.assets["top.css"]
をSprockets::Railtie.build_environment(Rails.application)["top.css"]
とかって書きかえればよいのだが、文字が多いのは嫌なので
class ApplicationController < ActionController::Base
before_action :set_assets
private
def set_assets
@assets = Rails.application.assets || ::Sprockets::Railtie.build_environment(Rails.application)
end
end
と書いてビューでは@assets["top.css"]
のような形で使うことにした。
参考:
Rails.application.assets is nil in production · Issue #237 · rails/sprockets-rails