Rails 3 has some unobtrusive JavaScript which is pretty cool.
But I was wondering what the best way is to include additional JavaScript for a particular page.
For example, where I might have previously done:
<%= f.radio_button :rating, 'positive', :onclick => "$('some_div').show();" %>
We can now make it unobtrusive with something like
<%= f.radio_button :rating, 'positive' %>
# then in some other file
$('user_rating_positive').click(function() {
$('some_div').show();
}
So I guess my question is where/how to include that JavaScript? I don’t want to fill up the application.js
file because this JavaScript is only applicable to this one view. Should I include a custom JavaScript file for each page somehow, or stick it in an instance variable that the header looks for?
If you don't want to use the asset pipeline or the complex work arounds to get that necessary page specific javascript (I sympathise), the simplest and most robust way, which achieves the same as the answers above but with less code is just to use:
Note: this does require one more http request per include tag than the answers which use
content_for :head
You shouldn't be loading your JS or CSS files outside of the asset pipeline because you lose out on important features that make Rails so great. And you don't need another gem. I believe in using as few gems as possible, and using a gem isn't necessary here.
What you want is known as "Controller Specific Javascript" ("Action Specific Javascript is included at the bottom). This allows you to load a specific JavaScript file for a specific CONTROLLER. Trying to connect your Javascript to a View is kind of... backwards and doesn't follow the MVC design pattern. You want to associate it with your Controllers or actions inside your Controllers.
Unfortunately, for whatever reason, Rails devs decided that by default, every page will load every JS file located in your assets directory. Why they decided to do this instead of enabling "Controller Specific Javascript" by default I will never know. This is done through the application.js file, which includes the following line of code by default:
This is known as a directive. It's what sprockets uses to load every JS file in the assets/javascripts directory. By default, sprockets automatically loads application.js and application.css, and the require_tree directive loads every JS and Coffee file in their respective directories.
NOTE: When you scaffold (if you aren't scaffolding, now is a good time to start), Rails automatically generates a coffee file for you, for that scaffold's controller. If you want it to generate a standard JS file instead of a coffee file, then remove the coffee gem that is enabled by default in your Gemfile, and your scaffold will create JS files instead.
Ok, so the first step to enabling "Controller Specific Javascript" is to remove the require_tree code from your application.js file, OR change it to a folder within your assets/javascripts directory if you still need global JS files. I.E.:
Step 2: Go into your config/initializers/assets.rb file, and add the following:
Insert the Controller names that you want.
Step 3: Replace the javascript_include_tag in your application.html.erb file with this (note the params[:controller] part:
Restart your server and viola! The JS file that was generated with your scaffold will now only load when that controller is called.
Need to load a specific JS file on a specific ACTION in your controller, I.E. /articles/new ? Do this instead:
application.html.erb:
config/initializers/assets.rb:
Then add a new folder with the same name as you controller in your assets/javascripts folder and put your js file with the same name as your action inside. It will then load it on that specific action.
What I like to do is include the per-view Javascript in a
content_for :head
block and thenyield
to that block in your application layout. For exampleIf it's pretty short then:
or, if longer, then:
Then, in your layout file
Ok so maybe this is like the worst work around ever but i creat a controller method that just rendered out the .js file
Controller
View
if for some reason we don't want to do this then let me know.