Loading Controller-specific Assets with Sprockets v3.0

Posted on May 20, 2016 by Carsten Zimmermann

Going from Rails v4.2.4 to v4.2.6 – a mere patchlevel update, mind you – became a Yak-shaving nightmare: Upgrading two other gems that broke with v4.2.6 brought in Sprockets v3.x. And that broke our little logic to include controller-specific javascript.

We have separate JS files following a naming convention that should be included in the layout when they are present. The path is constructed as follows:

module ApplicationHelper
  def controller_specific_js
    "modules/#{controller_name}"
  end
end

In the pre-update version, we included the Javascript like this:

# somewhere in our layout file:
- if Rails.application.assets.find_asset controller_specific_js
  = javascript_include_tag controller_specific_js

find_asset was gone post-update and none of the discussed solutions in issue rails/rails#311 were working for us. assets_manifest[filename] was always empty and we didn’t want to pass asset_path(filename) without really knowing if the asset exists.

However, we noticed that existing assets had the literal "/assets/" in their path only when found. We used that to determine whether or not to out the JS include statement:

module ApplicationHelper
  def controller_specific_js
    asset_path("modules/#{controller_name}")
  end
end
# somewhere in our layout file:
- if controller_specific_js =~ /\/assets\//
  = javascript_include_tag controller_specific_js

Kinda ugly, yes, but seemed to get the job done. Only it didn’t. Apparently asset_path has some additional behind-the-scenes magic that, to add insult to injury, behaves differently in development than on staging/production of course: It requires an explicit filename extension to locate the asset.

Behold the final version:

module ApplicationHelper
  def controller_specific_js
    "modules/#{controller_name}"
  end
end
# somewhere in our layout file:
- if (asset_path(controller_specific_js + '.js') =~ /\/assets\//)
  = javascript_include_tag controller_specific_js

YMMV, of course, but we hope it helps.

comments powered by Disqus