image_tagで付加される画像のタイムスタンプを、production環境でも画像ファイルが更新されたタイミングで更新されるようにする
image_tagで画像を表示した際に、srcの後ろに付くタイムスタンプは
基本的には File.mtime(image_path) なので、画像ファイルの最終更新時刻です。
image_tag 'rails.png' #=> <img src="/images/rails.png?1298610241" alt="Rails" />
なので、developement環境では画像ファイルをtouchしてあげたりすると、タイムスタンプも更新されます。
しかし、production環境ではtouchしても更新されません。(passengerなり、サーバをリスタートすれば更新されます)
なぜこうなるかは、ActionView::Helpers::AssetTagHelper の rails_asset_id メソッドを見るとわかります。
# File actionpack/lib/action_view/helpers/asset_tag_helper.rb def rails_asset_id(source) if asset_id = ENV["RAILS_ASSET_ID"] asset_id else if @@cache_asset_timestamps && (asset_id = @@asset_timestamps_cache[source]) asset_id else path = File.join(ASSETS_DIR, source) asset_id = File.exist?(path) ? File.mtime(path).to_i.to_s : '' if @@cache_asset_timestamps @@asset_timestamps_cache_guard.synchronize do @@asset_timestamps_cache[source] = asset_id end end asset_id end end end
最初1回は、File.mtime(path) をちゃんと取ってくれるのですが、
その際に、@@asset_timestamps_cache[source] = asset_id で、キャッシュして、
以降は、そのキャッシュが使われます。
で、@@cache_asset_timestamps が何かを見ると
# File actionpack/lib/action_view/helpers/asset_tag_helper.rb def self.cache_asset_timestamps @@cache_asset_timestamps end # You can enable or disable the asset tag timestamps cache. # With the cache enabled, the asset tag helper methods will make fewer # expense file system calls. However this prevents you from modifying # any asset files while the server is running. # # ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false def self.cache_asset_timestamps=(value) @@cache_asset_timestamps = value end @@cache_asset_timestamps = true
booleanの値です。
さらにセッターの上に今回の答えがコメントで書かれてますが、
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false すれば、
毎回 File.mtime(path) してくれるようになります。
なので、initializersとかに、適当なファイルを作って、
# config/intializers/cache_asset_timestamp.rb とか ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
だけ書いておけば、production環境でもtouchしたらタイムスタンプが更新されるようになります。
ちなみに、development環境は、config/environments/development.rb で
config.cache_classes = false
になってると思いますが、cache_classesがfalseだと、
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
が実行されるので、development環境では何もしなくてもタイムスタンプが更新されるっぽいです。