Rails2.0.2のjavascript_include_tagのcacheはRailsがルート以外(/appとか)で動いてるとバグる
タイトルの通り。
たとえば、mongrel_clusterなんかをつかってて、
prefix: /rails
とかやってて、アプリのURLが
http://taslam.example.jp/sample
なんかになってると、javascript_include_tag(*, :cache => 'cache')の動作がおかしくなる。
Railsのソースを追ってみると、
/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_view/helpers/asset_tag_helper.rb
def join_asset_file_contents(paths) # ASSETS_DIR => /home/admin/rails/sample/public # paths => ["/sample/javascripts/prototype.js", ...]) # /home/admin/rails/sample/public/app/javascripts/prototype.js を読み出そうとしている paths.collect { |path| File.read(File.join(ASSETS_DIR, path.split("?").first)) }.join("\n\n") end
/sampleで動かすと、scriptタグのsrcに記載されるパス(URL)は"/sample/javascripts/prototype.js" という具合になる。
しかし、サーバ内でのパスは、RAILS_ROOT/javascripts/prototype.js のままのはず。
javascript_include_tagにもどってもういちどみてみる。
def javascript_include_tag(*sources) options = sources.extract_options!.stringify_keys cache = options.delete("cache") if ActionController::Base.perform_caching && cache joined_javascript_name = (cache == true ? "all" : cache) + ".js" joined_javascript_path = File.join(JAVASCRIPTS_DIR, joined_javascript_name) write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources)) javascript_src_tag(joined_javascript_name, options) else expand_javascript_sources(sources).collect { |source| javascript_src_tag(source, options) }.join("\n") end end
write_asset_file_contentsは、第1引数にキャッシュファイルのパス、第2引数にファイルのパスの配列を渡すと、キャッシュファイルにまとめてくれるメソッド。(キャッシュが既にあれば処理しない)
内部で、さっきみたjoin_asset_file_contentsを呼んでる。
compute_javascript_pathsは、ファイル名の配列(['prototype', 'effects',...]とか)を受け取って、それぞれのサイトルートからのパス(/sample/javascripts/prototype.js)の配列を返すメソッド。
けど、ここではサイトルートからのパスなんていらないような・・・
ここでほしいのは、読み出すために必要なサーバ内のパスだよね。
あんまり深く考えるのは面倒だったので、とりあえず適当なところで上書きしてやった。これだと、「/スクリプトのパス」での指定が出来ないけど、使わないからまぁいいや。
module ActionView module Helpers module AssetTagHelper def javascript_include_tag(*sources) options = sources.extract_options!.stringify_keys cache = options.delete("cache") if ActionController::Base.perform_caching && cache joined_javascript_name = (cache == true ? "all" : cache) + ".js" joined_javascript_path = File.join(JAVASCRIPTS_DIR, joined_javascript_name) write_asset_file_contents(joined_javascript_path, sources.collect{ |source| "/javascripts/#{source}.js"}) javascript_src_tag(joined_javascript_name, options) else expand_javascript_sources(sources).collect { |source| javascript_src_tag(source, options) }.join("\n") end end end end end