Where the assets live
Before rails 3.1, we'd lump all our javascript and stylesheets in the "junk drawer" that is public. No more. Now they can go in 3 different dirs depending on their purpose:
- app/assets for things that our your application code
- lib/assets for shared-ish things (not sure I grok what I'd put here yet)
- vendor/assets to put things that your app uses but is provided by others
So this gives places to put stuff, which is nice, but only the beginning. The killer features (for me) are the ability to package assets and manage dependencies. To see how this works, take a look the app/assets/application.js file you get when generate a new rails 3.1 app.
Nothing but comments, weird huh. That's because this is what we're calling a "manifest file" which is basically just a file that requires in other files. When you include /assets/application.js at runtime, rails will package all the files you required and concatenate (and optionally minimize) them. Let's look at those last 3 lines, as there's magic in them thar comments. The first 2 require in jquery and jquery_ujs. It seems like this must mean that there are jquery.js and jquery_ujs.js files somewhere in one of the assets directories, but this isn't so. That's because gems can contribute to the asset pipeline as well. More on this later. The last line says to include all files in this directory or subdirectories as well. In our apps so far we find it nice to have 2 such manifest files, vendor/assets/javascripts/vendor.js and app/assets/javascripts/application.js. Not sure I can call this "best practice" or not yet, just that it seems nice to us so far.
It's also worth pointing out that files that need to processed (eg coffeescript and sass) will be handled automatically as well. Simply drop a file named whatever.coffee into the /app/assets directory and it will be compiled and included into application.js
Where this all gets more interesting to me is where we have files in the application that depend on each other. Files that are required can have requires of their own. The example I have in my app is coffeescript class inheritance. Imagine a couple classes like so:
When you're building apps with a lot of front end code, it's to be able to organize code with each class in it's own file. But this means you have to make sure to have the script that brings in fruit before apple. With the ability to require in rails 3.1, this problem is nicely solved for us. If we add a require statement to apple.coffee like so, the asset pipeline will take care of making sure things are in the correct order:
This is a huge win for me, as before this I was naming files with numbers such as 1_fruit.coffee to get around this problem. Yuck.
I mentioned earlier that I'd talk about assets living in gems. This is a feature that allows you to take front end code and easily share it between multiple projects. In my next post I'll talk about my experience building a rails 3.1 asset containing gem.