Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Some brief instructions on how to use Sprocket 2 in Rails to get CoffeeScript
powered JS and SASS powered CSS with YUI compression all via the magic of rack.
This stuff will be native in Rails 3.1 and the layout of the files on the
filesystem will be different but this guide will get you working with it
while we wait for all that to finalize.
Ignore the number prefixes on each file. This is just to ensure proper order in the Gist.
It's based on eric1234 gist https://gist.github.com/911003. ijust made it 3.1 compliant in terms of convention
gem 'coffee-script'
gem 'yui-compressor', :require => 'yui/compressor'
gem 'sass'
gem 'json' # sprocket dependency for Ruby 1.8 only
gem 'sprockets', :git => 'git://github.com/sstephenson/sprockets.git'
# Sprockets needs to build JS file. On mac it uses apple java compiler, on production server (linux for example) you need to
# install this gem
group :production do
gem "therubyracer"
end
# Config a Sprockets::Environment to mount as a Rack end-point. I like to use a subclass
# as it allows the config to be easily reusable. Since I use the same instance for
# all mount points I make it a singleton class. I just add this as an initializer to my
# project since it is really just configuration.
class AssetServer < Sprockets::Environment
include Singleton
def initialize
super Rails.root.join('app', 'assets')
paths << 'javascripts' << 'stylesheets'
if Rails.env.production?
self.js_compressor = YUI::JavaScriptCompressor.new :munge => true, :optimize => true
self.css_compressor = YUI::CssCompressor.new
end
end
end
# Mount the rack end-point for JavaScript and CSS.
MyApp::Application.routes.draw do
# Add this line
mount AssetServer.instance => '/assets'
end
# Put this in your assets/javascripts/application.js directory and call /assets/application.js in your browser
# You need to have jquery and jquery_ujs files (jquery_ujs is sometimes named rails.js)
#
# In your layout just add
#
# <%= javascript_include_tag "/assets/application" %>
#
# In Rails 3.1 you could even do
#
# <%= javascript_include_tag "application" %>
#
//= require jquery
//= require jquery_ujs
//= require_tree .
# Put this in your app/assets/javascripts directory, it will be included when you call /assets/application.js in your browser
alert 'hello world'
// Put this in your app/assets/stylesheets directory and call /assets/application.css in your browser
// In your layout just add
//
// <%= stylesheet_link_tag "/assets/application" %>
//
// In Rails 3.1 you could even do
//
// <%= stylesheet_link_tag "application" %>
//
/*
*= require_tree .
*/
// Put this in your app/assets/stylesheets directory and call /assets/application.css in your browser
body {margin: 2px + 5px}
Sprockets 2 has a lot more under the hood but this gets you started.
A few things not covered:
1. Anything supported by Tilt can be used as a template engine
(not just Sass and CoffeeScript).
2. Although Sass has native abilities to include other files, Sprockets 2
gives the ability to all formats through special comments like:
// =require "foo"
It's special commands can be fairly powerful (like requiring an entire
directory or tree). NOTE: Use the comment character relevant for the
language. So coffescript should be:
# =require 'foo.js'
Then you can create 'foo.js.coffee' and when served it will be as one
file.
3. Sprockets 2 has the ability to pre-compile the assets for maximum speed.
Also useful when the deployment environment doesn't support a template
language (like CoffeeScript).
@raroni

This comment has been minimized.

Copy link

commented Apr 27, 2011

This is awesome, thanks a lot. I can't seem to get scss mixins working. I get an Sass::SyntaxError: Undefined mixin 'colored_button'.

I tried using scss's @import instead, but with Sprockets and scss 3.1 (instead of the Sass Rails' plugin), it does not know my stylesheet asset root - so I need to specify relative paths everywhere :(

Have you found a nice way to get mixins working?

@victusfate

This comment has been minimized.

Copy link

commented May 11, 2011

would you believe i was missing:
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>

in my old layout (migrating from 2.3.4 to 3.1beta1)

@hassox

This comment has been minimized.

Copy link

commented May 17, 2011

What happens with this setup in production?

@sgruhier

This comment has been minimized.

Copy link
Owner Author

commented May 17, 2011

what do you mean?
I have a site in beta test with this settings and it works.

@hassox

This comment has been minimized.

Copy link

commented May 17, 2011

I mean how do I configure this to compile once / not compile in a particular environment vs re-compiling everytime in development. I'm a bit of a noob to it.

@hassox

This comment has been minimized.

Copy link

commented May 17, 2011

Never mind... I found it: When caching is enabled, e.g. in production mode, SprocketsController uses Rails page caching to save the concatenated output to public/sprockets.js

@sgruhier

This comment has been minimized.

Copy link
Owner Author

commented May 17, 2011

Yes assets are compressed and cahced in production mode.

@raroni

This comment has been minimized.

Copy link

commented May 17, 2011

Are you guys not bugged by the fact sprockets does not yet support Sass/SCSS mixins? Or is it just me...? :)

@sgruhier

This comment has been minimized.

Copy link
Owner Author

commented May 17, 2011

Not really because I don't use Sass/SCSS mixins

@julian7

This comment has been minimized.

Copy link

commented May 17, 2011

@rasmusrn you can use include if the two assets are in the same place (eg. in lib/assets/stylesheets), but they don't work if they're in a different one (AFAIK tilt has the fix: rtomayko/tilt@0bc5bb7). I think the problem is sass gem's workflow is broken: sprockets reads css / scss files according to the manifest file (application.css), running scss transformation on each file. Then, the generated css files get concatenated. In the end, sprockets minifies this css with sass.

It means you lose the most powerful feature of sass: the free usage of variables, functions and mixins in separate files.

As far as I know tilt has some fixes for @import bug, but it won't cure all of our problems. We'll have to @import all the @mixin's in every scss file where we want to use them, which can be tough for media queries, where you have only one chance to define a specific media (eg. only the first @media print {} will be used, all the others will be ignored).

@hassox

This comment has been minimized.

Copy link

commented May 17, 2011

@sgruhier well caching is the case whne using rails sprockets.. but the method detailed above does not use this engine...

@hassox

This comment has been minimized.

Copy link

commented May 17, 2011

@rasmusrn I setup tilt from trunk last night and this got the mixins working correctly for me.

@stan

This comment has been minimized.

Copy link

commented May 18, 2011

I guess I must be missing something..
NoMethodError (undefined method `process_javascript_include_tag_directive' for #Sprockets::DirectiveProcessor:0x000000123358d0)

Update :
Ends up, comments not allowed in application.js & application.css.. Removed those and it works now fine.

@julian7

This comment has been minimized.

Copy link

commented May 18, 2011

@rasmusrn @hassox I tried last tilt trunk last night with scss. imports work, requires don't.

@victusfate

This comment has been minimized.

Copy link

commented May 18, 2011

@stan I'll be messing around with apps after work. If you're still stuck maybe I can give a hand (I'm a learning grade rubyist)
I started with a fresh Links app with the git repo's rails --edge and it worked ok (I did that from my phone on a terribly slow terminal yesterday). It helped me figure out what was borked in my migration from rails 2.3.4 to 3.1beta of a semantic twitter app

With a fresh app you don't have to change much to get it using sprockets. I just renamed a scaffold.css to a scaffold.css.scss

@john

This comment has been minimized.

Copy link

commented Jun 20, 2011

Having trouble getting javascript_include_tag to work with this setup. I have a rails 3.0.5 app, and am trying to config 3.1-style assets. I've bundled the gems above, added AssetServer to the initializers and verified that it's being loaded, mounted AssetServer in routes.rb, and then called stylesheet_link_tag "/assets/application" from my layout template.

Keep getting routing errors saying application.js can't be found. Am I overlooking something, or doing something stupid? Or has sprockets 2 changed? It seem like a moving target.

Pulling my hair out, any help hugely appreciated.

@leifbladt

This comment has been minimized.

Copy link

commented Jun 21, 2011

Sprockets has changed, more precisely the paths moved from Environment to another class. Unfortunately this doesn't help me to fix the configuration...

@john

This comment has been minimized.

Copy link

commented Jun 21, 2011

Looks the paths are added with append_path('javascripts'); append_path('stylesheets'), which comes from the module Trail:

http://rdoc.info/github/sstephenson/sprockets/master/Sprockets/Trail

Still not working for me tho :-/

@leifbladt

This comment has been minimized.

Copy link

commented Jun 22, 2011

With latest beta11, the append_path did the trick for me.

@diegoeche

This comment has been minimized.

Copy link

commented Jul 15, 2011

Omg, this was exactly what I needed. Thanks!

@niuage

This comment has been minimized.

Copy link

commented Jul 28, 2011

https://gist.github.com/1112393 (I've made some changes to fit my needs)
I'm asking a question in this gist, if anyone can help me on this, it'd be great :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.