This is a comprehensive guide to upgrading a Ruby on Rails 3 application to Rails 3.1. It also includes instructions for updating the compass gem. Lets get started!
gem 'rails', '3.1.0'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', " ~> 3.1.0"
gem 'coffee-rails', "~> 3.1.0"
# If you use compass:
# gem 'compass', git: 'https://github.com/chriseppstein/compass.git', branch: 'rails31'
# If you use mysql, make sure it's above version 3:
# gem 'mysql2', '> 0.3'
$ bundle update
$ bundle install
Auto vs Manual
If you like you can do an auto upgrade, where you type in the console “bundle exec rake rails:update” and then it will go through each new file with you (press ‘d’ to see the differences between yours and the new file).
However if you are worried about over-writing your code you can follow along below. I would read on anyway in case the auto method misses something.
Add missing file wrap parameters
$ touch config/initializers/wrap_parameters.rb
# insert following code into config/initializers/wrap_parameters.rb:
# Be sure to restart your server when you modify this file.
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
wrap_parameters format: [:json]
# Disable root element in JSON by default.
self.include_root_in_json = false
Update environment files with assets stuff
# 1 - replace this:
# If you have a Gemfile, require the gems listed there, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(:default, Rails.env) if defined?(Bundler)
# 1 - with this:
# If you precompile assets before deploying to production, use this line
Bundler.require *Rails.groups(:assets => %w(development test))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
# 2 - then add these in (underneath class Application < Rails::Application)
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
# also while in development.rb, REMOVE this line if it's there:
config.action_view.debug_rjs = true
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to Rails.root.join("public/assets")
# config.assets.manifest = YOUR_PATH
config.assets.js_compressor = :uglifier
config.assets.css_compressor = :scss
# Configure static asset server for tests with Cache-Control for performance
config.serve_static_assets = true
config.static_cache_control = "public, max-age=3600"
Here there should be no folders at all. We instead put them into assets. We also should create the other assets locations in lib and vendor:
$ mkdir app/assets
$ git mv public/images app/assets/images
$ git mv public/stylesheets app/assets/stylesheets
$ mkdir vendor/assets
$ mkdir lib/assets
Note: If you have .sass or .scss files you will have to rename them to .css.sass or .css.scss
In this file put the following text up the top (note that you don’t have to uncomment the require stuff – “//=” will work fine):
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//= require jquery
//= require jquery_ujs
//= require_tree .
Finally you could ignore directories and trees and just call certain files with “//= require posts” => loads posts.js
Now we do the same thing but for the stylesheets/application.css
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require_tree .
<%= stylesheet_link_tag "application" %>
<%= csrf_meta_tags %>
= stylesheet_link_tag "application"
Other little tweaks
Add these to your .gitignore file:
Stylesheets: Images and Manifest files
Rails provides these helpers, which will find your images:
# .sass OR .scss (without .erb on the end)
image-path("rails.png") becomes "/assets/rails.png"
asset-url("rails.png", image) becomes url(/assets/rails.png)
# eg for .sass or .scss file:
Manifest files are the ones that tell Sprockets which files to concatenate into one big file. I had an issue with referencing folders in the vendor/assets directory. For example, I didn’t want to load every single css file (“require_tree .”), but instead wanted to load every css file in a folder situated in my vendor directory; “vendor/assets/stylesheets/layout/”. If in my application.css file I went “require_tree ./vendor” it couldn’t find it, and I didn’t really want to have to write “require_tree ../../../….blah blah”.
Anyway it seems the best solution I found was to create a manifest file in vendor (say “vendor.css”, and in that file I could go “require_tree ./vendor”. Then in application.css I would reference the vendor file “require vendor”. Comment if you have a better solution.
Optional: Getting Compass to work
I had the issue that my stylesheets were in app/stylesheets and needed to be app/assets/stylesheets. Here are the steps I took:
- went to initializers/compass.rb and commented out any path references
#css_dir = ‘public/stylesheets’
#sass_dir = ‘app/stylesheets’
- moved everything in app/stylesheets to app/assets/stylesheets
- deleted what was had been compiled by sass in public (screen.css, print.css, ie.css)
- renamed all my .scss files to .css.scss
- moved all my plugin and random stylesheets I never edit from app/assets/stylesheets to vendor/assets/stylesheets
- created/renamed application.css.scss in app/assets/stylesheets
- copied everything in screen.css.scss to application.css.scss
- in application.css.scss.erb I did a find for “url” and replaced the url’s with asset_path ‘asset_name’ (eg url(‘../images/top_x.jpg’) => url( asset_path ‘top_x’)
- also in application.css.scss.erb I deleted the “require_tree .” because this was loading my partials again (they are already included in my application.css.scss.erb)
Note: if you want an all-in-one resource to become an expert in ruby on rails 3, don’t bother with textbooks – just get this video tutorial series (highly recommended): Ruby on Rails Tutorial