Rails page specific JavaScript and CSS

In a Rails project that I was working on, I wanted to come up with a way to separate the JavaScript and CSS code  to be page specific.    I could do this in JavaScript with some namespace techniques such as discussed in the article Javascript Namespace Declaration   CSS appears to pose more of a problem and I was not able to find a good namespace solution other than to use prefixes.

Using Helper Methods

I finally stumbled upon a nice technique using helper methods as described in the selected answer to the post Rails 3.1 asset pipeline: how to load controller-specific scripts?

The following addresses the problem with JavaScript  – I’ll show how this can be extended to CSS later.

The solution described was to add a yield in the layout head section such as:

<%= yield(:head) %>

and call a helper method in the page view:

<% javascript 'name_of_the_js_file' %>

The helper method in application_helper.rb would look like:

def javascript(*files)
  content_for(:head) { javascript_include_tag(*files) }
end

Caching

I’m using page caching to speed up my Rails site.    Unfortunately this means that I can’t call the helper method shown above in the page view, since the page may be in the cache.

caches_action :index, :layout => false

Calling helper method from the layout

Since I’m not caching the layout, I decided to move the helper method call there. Suppose though that I want to more finely control which actions I respond to with an insertion of specific JavaScript and CSS? In that case, I can qualify my calls to helper methods based on controller.action_name. I found out about using the method action_name in the post Getting the current action and controller from the view in Rails   There is also a reference to this in the Rails Guide – Action Controller Overview.

This is what I ended up with in one of my layouts (supports edit views), along with support for CSS:

<!DOCTYPE html>

<%
if (controller.action_name == "edit") || (controller.action_name == "update")
  javascript 'contacts_edit'
  stylesheet 'contacts_edit'
end
%>

<html>
<head>
  <title>Contacts2Web</title>
  <%= stylesheet_link_tag    "application", :media => "all" %>
  <%= stylesheet_link_tag    "contacts", :media => "all" %>
  <%= yield(:head_stylesheet) %>
  <%= javascript_include_tag "application" %>
  <%= yield(:head_javascript) %>
  <%= csrf_meta_tags %>
</head>
<body>

The JavaScript and CSS files referenced above are located in:

app/assets/javascripts/contacts_edit.js.coffee

app/assets/stylesheets/contacts_edit.css.scss

JavaScript/CSS Helper methods

My helper methods in application_helper.rb looked like:

  def javascript(*files)
    content_for(:head_javascript) { javascript_include_tag(*files) }
  end

  def stylesheet(*files)
    content_for(:head_stylesheet) { stylesheet_link_tag(*files) }
  end

Assets Precompile

For production deployment, assets are precompiled.  I needed to make one further change to make sure that the JavaScript and CSS inserted via my helper methods were included in the precompiled assets.

production.rb:

  # Precompile additional assets
  #
  # Here we are including files that are conditionally included with helper methods
  # javascript & stylesheet from application_helper.rb.   These files are not
  # included in the application.js and application.css manifests and thus would
  # not by default be precompiled with "bundle exec rake assets:precompile"
  # unless included in this directive.
  config.assets.precompile += %w( contacts_edit.css contacts_edit.js)

 

That’s it!  Using helper methods to insert page specific JavaScript & CSS in the layout, I was able to achieve a simple form of namespacing.

Advertisements

2 responses to “Rails page specific JavaScript and CSS

  1. Hey would you mind stating which blog platform you are utilizing? I’m looking to start my own blog in the near future but I am getting a difficult time choosing in between BlogEngine/Wordpress/B2evolution and Drupal. The reason I ask is because your layout seems different then most blogs and I’m looking for some thing totally unique. P.S My apologies for getting off-topic but I needed to ask!

    Like

  2. I am using WordPress with the Coraline theme. I chose the full-width page template that removes the sidebar (putting widgets at the bottom of the page).

    Hope that helps!

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s