Phusion white papers Phusion overview

Phusion Blog

Rendering Rails 3.1 assets to string

By Hongli Lai on August 14th, 2011

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.