How I Do Javascript in Ruby on Rails

I have been asked recently how I do my javascript in a javascript-intensive production application. There are a number of things to consider when you start rolling out huge amounts of javascript in your application. If you aren't careful, it can become an unwieldy beast very quickly. It comes down to two major things to keep in mind: organize and namespace. To level set, I would like to point out that I am a purist when it comes to javascript. I find that completely separating the html, css, javascript, and server side helps to keep things clean and well designed. I always blast the prototype and script.aculo.us libraries from my projects and I never use rjs templates. I write javascript such that it keys off the metadata in the DOM to operate, so no javascript is ever generated by the server. This makes the javascript easy to test and debug, and forces you to think hard about the design of your client layer. I believe that it has helped me to produce a higher quality of code and I continue to use and refine my process.

Organize Your Scripts

It is very important to come up with a solid organizational scheme. Having a clean and consistent way of storing the code will make it easy to lookup and easy to know exactly what everything is used for. In my applications, I follow two main tenets:
  • Application specific plugins should be noted. I always name jQuery plugins that are specific to my product as jquery-productname-plugin-name.js. That has been working out pretty well to clearly identify them against the plugins you downloaded.
  • Javascript file names should match the controller action they correspond to and be nested in a folder matching the controller name. So your /products/new action's javascript would be in /public/javascripts/products/new.js.
I also arrange my css the same way. Doing that makes it really easy to know what is being used and where. When you blast a controller, you can safely blast the javascript and css directories matching it if you strictly followed the pattern.

Be Smart About Includes

Another thing I do is always have 2 javascript and 2 css files per page. One is the global template group and the other is the page specific group. In my application template I have this: [ruby]<%= javascript_include_tag "global.js", "jquery-tablesorter-min.js", ..., :cache => true %> <%= yield :tail %>[/ruby] Similarly, I have the same tags for my css but with yield :head instead. Then in my view, I do [ruby]<%- content_for :tail do -%> <%= javascript_include_tag "controller/action.js" %> <%- end -%>[/ruby]

Namespace!

There are three different types of javascript that will be attached to your page: in the document ready, as a plugin, or as static namespaced functions. The code in your document ready is fine. It should be pretty lean, but if there are lots of unique event handlers or whatnot, it can get pretty big. Your custom plugins should always have cool and unique names. So what do you do with the rest of the javascript? Namespace it as static functions. I don't typically write a lot of this, but sometimes it makes sense to separate code into some logical parts. Mine would look something like this: [js]var ControllerAction = { someFunction: function() { ... } }[/js] Sticking with the controller and action naming will always let you know where the functions you are calling came from. If something happens down the road and it gets included in Controller2's Action2, I can look at the function calls and know exactly where ControllerAction.someFunction() came from. Obviously, it isn't part of the Controller2Action2 namespace, so I need to look in /public/javascripts/controller/action.js to find it. So that is the organization of my Rails application javascript in a nutshell. Trying to stay as close to the Rails naming conventions as possible has helped me to keep a handle on the huge amounts of javascript I have written. Always remember, consistency is key to maintainability.