10 Nov 2010

Rails 3 javascript_include_tag


The below issue is already fixed in rails.

After installing the _jquery_ujs _driver for a Rails 3 app, today it started acting up when I tried using the Cycle jQuery plugin. Specifically, the following code in application.js would create twice as many pager anchors as expected.

$(document).ready(function(){
  $('.featured').cycle({
      fx: 'fade',
      timeout: 5000,
      speed: 600,
      pager: '#featured-controls',
      pauseOnPagerHover: true,
      pause: true,
      pagerAnchorBuilder: function(idx, slide) { return '<a href="#">'; }
  });
});

At first I thought it was a problem with my HTML code as I was using nested _divs _(by chance two internal _divs _per container _div _I wanted to cycle), but that wasn’t the reason. Tracing the problem, I noticed, that application.js would get executed twice, and lo and behold, there it is at the top of the source: application.js included twice. Hmm, that’s strange, my includes look like this:

<%= javascript_include_tag :defaults %>
<%= javascript_include_tag 'jquery.cycle.min' %>

In application.rb, I made the following configuration as suggested by the jquery_ujs github’s README:

config.action_view.javascript_expansions[:defaults] = %w(jquery rails application)

As it turns out, however, rails is very smart about javascript files and when someone includes :defaults **(and in :defaults only) it will automatically append application.js to the list of files to include. Let’s take a look at **actionpack/lib/action_view/helpers/asset_tag_helper.rb:

def expand_javascript_sources(sources, recursive = false)
  if sources.include?(:all)
    all_javascript_files = collect_asset_files(config.javascripts_dir, ('**' if recursive), '*.js')
    ((determine_source(:defaults, @@javascript_expansions).dup & all_javascript_files) +
      all_javascript_files).uniq
  else
    expanded_sources = sources.collect do |source|
      determine_source(source, @@javascript_expansions)
    end.flatten
    expanded_sources << "application" if sources.include?(:defaults) && File.exist?(File.join(config.javascripts_dir, "application.js"))
    expanded_sources
  end
end

Removing _application _from the **javascript_expansions[:default] **configuration removes the duplicate application.js and Cycle now works properly.


blog comments powered by Disqus