Sankalp Singha
Sankalp Singha

Reputation: 4546

Adding Page Specific JS in Rails 4.0.1

I am trying to do something like this in my application.js.coffee manifest file

#= require jquery.min
#= require jquery.turbolinks
#= require jquery_ujs
#= require private_pub
#= require turbolinks
#= require ckeditor/init
#= require bootstrap


$ ->
  if $('body').hasClass 'page'
    #= require jquery.parallax-1.1.3
    #= require jquery.scrollTo.min
    #= require jquery.easing.1.3
    #= require waypoints.min
    #= require jquery.mousewheel
    #= require jpreLoader
    #= require custom
    #= require maps
    #= require jquery.flexisel

  else
    #= require jquery.slimscroll.min
    #= require morris
    #= require lanceng
    #= require editable/bootstrap-editable
    #= require editable/rails
    #= require jquery.countdown

Is this not correct? I want to add page specific JS and I am sure that I have added the <%= controller_name %> in the body class also and this is the method I am using for page specific CSS.

However, in my source I can only see the following :

<!-- Javascript  -->

<script data-turbolinks-track="true" src="/assets/jquery.min.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/jquery.turbolinks.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/jquery_ujs.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/private_pub.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/turbolinks.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/ckeditor/init.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/ckeditor/ckeditor.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/bootstrap.js?body=1"></script>
<script data-turbolinks-track="true" src="/assets/application.js?body=1"></script>

Is this method not correct? If not then what is the method of doing it?

Upvotes: 0

Views: 266

Answers (2)

Paul Richter
Paul Richter

Reputation: 11072

Unfortunately the problem you're seeing is because the manifest (the require statements) is evaluated server-side. So your javascript if statement won't filter or prevent anything from loading, because the target JS files are already loaded by this point. In fact, if you take a look at the rendered application.js in the browser, you'll probably see an empty if block.

There are a couple of ways you can do this (that I'm aware of). If you take a look at the Rails Asset Pipeline guide Controller-Specific Assets, it advises:

...include controller specific stylesheets and JavaScript files only in their respective controllers using the following:

<%= javascript_include_tag params[:controller] %> 
or 
<%= stylesheet_link_tag params[:controller] %>

When doing this, ensure you are not using the require_tree directive, as that will result in your assets being included more than once.

Additionally, a collegue has been using a gem called Paloma for precisely this purpose. I have not used it myself, so I cannot give you direct advice or examples, however I mention it because it appears to help streamline the loading of not only controller-specific, but also action-specific assets.

Upvotes: 1

DiegoSalazar
DiegoSalazar

Reputation: 13521

The #= require statements are proprocessors that run on the serverside before your code runs on the page therefore not even the jQuery ready $ -> function will work which is why you're not seeing any of the requires there included on the page.

I'm going to have to stop right here and just say that it is much better to have Rails asset pipeline concatenate and minify your javascript assets into one file and serve them all at once than to have each page load a different javascript file. The reason is that it is better for the user to download 1 large file and cache it than to have to download several files with each request. This is specially true on mobile platforms. I highly recommend rethinking your strategy.

Further reading:

Upvotes: 3

Related Questions