コンテキスト
HerokuでRailsアプリケーションを運用する際は、本番環境とは別にステージング環境を用意することがよくあります。
ステージング環境では通常、Heroku上のRACK_ENVやRAILS_ENVといった環境変数をstagingにします。
これらの環境変数がstagingになっていると、config/environments/staging.rbの設定値を読み込んでアプリケーションが起動します。
問題
ただし、assets(CSSやJavaScript等)のprecompile時は必ずしもstaging.rbが読み込まれるわけではないので注意が必要です。
たとえば、application.cssとは別にawesome.cssをprecompileしたい場合は以下のような指定が必要になります。
config.assets.precompile += %w( awesome.css )
通常こうした設定値はstaging.rbまたはproduction.rbに設定しますが、heroku_sanやgit pushでステージング環境にソースコードをデプロイするときはstaging.rbではなく、production.rbを読み込んでassets precompileされます。
staging.rbとproduction.rbを同時に変更している場合は、あたかもstaging.rbが読み込まれているように錯覚してしまいますが、先にstaging.rbだけを更新してHerokuにデプロイしたりすると、awesome.cssがprecompileされないため、以下のようなエラーが発生します。
ActionView::Template::Error (awesome.css isn't precompiled):
ステージング環境のエラーだからstaging.rbに問題があるのだろうと思い込んでると、永遠に解決しないので要注意です。
対応策
1. production.rbにassets precompile関係の設定を書く
assets precompile関係の設定値が本番環境とステージング環境で変わらないのであれば、常にproduction.rbに設定値を書いておくという解決策が選択できます。
変わったことをしないのであれば、これが一番手軽かもしれません。
2. デプロイ後に別途assets precompileを実行する
本番環境とステージング環境で設定を変える必要があるなら、コードのデプロイ後にherokuGemを使ってassets precompileを実行しましょう。
こうするとstaging.rbの設定値を使ってassets precompileしてくれます。
$ heroku run rake assets:precompile --app your-app-staging
3. user_env_compileプラグインを導入する
別途assets precompileを実行するやり方だと、ついassets precompileを忘れてしまう恐れがあります。毎回デプロイと同時に実行する方法はないでしょうか?
user_env_compileというHerokuのプラグインを導入すると、デプロイ時にstaging.rbの設定値を使ってassets precompileするようになります。
ただし、このプラグインは実験的なプラグインなので「予告なく削除されるかもしれない」という警告が出ます。
その点に留意した上で使用してください。
備考
ローカル環境でrake assets:precompileを呼び出した場合もproduction.rbが読み込まれます。development.rbではありません。
もしdevelopment.rbを使いたいのであれば、下のようにRAILS_ENVオプションをつけるとdevelopment.rbを読み込ませることができます。
$ rake assets:precompile RAILS_ENV=development