Rendering Rails 3.1 assets to string
The upcoming Rails 3.1 will come with a powerful asset pipeline, which is a framework for allowing developers to preprocess, concatenate, minify and compress Javascripts and CSS files. Javascripts can be written in CofeeScript, which is compiled on-the-fly to Javascript. Similarly, CSS can be written in Sass or SCSS, which are compiled on-the-fly to plain old CSS. Many people have already written about this topic.
Today we ran into a situation in which we wanted to render an SCSS file to a string so that we can put it in a JSON document. The way to do this is non-obvious. First try:
render :template => 'assets/stylesheets/api.css'
Rails complained that it cannot find this file in its search path, which only includes ‘app/views’.
Next try involved using the :file
option because it also searches in Rails.root
:
render :file => 'app/assets/stylesheets/api.css'
This time it successfully found the file, but couldn’t render it because there’s no :scss
template engine. Apparently the asset pipeline does not integrate into the Rails template engine framework.
After some code digging, it turned out that asset serving is completely powered by Sprockets. The Rack middleware responsible for serving the /assets
is Sprockets::Server
, which looks up asset information using a Sprockets::Environment
object. This object also handles rendering. The Rails integration allows such an object to be accessed through the YourApp::Application.assets
method.
So the correct way to render an asset to a string is as follows:
YourApp::Application.assets.find_asset('api.css').body
Here, YourApp
is your application’s module name as found in config/application.rb
.