Upgrading a Rails project from 2.3.x to 3.0.0

In order to upgrade your Ruby on Rails project to 3.0.0, rather than recreate your whole project structure and moving your app files across, I found it to be easier to update some of the files. Follow the instructions in this post to update your existing project to Rails 3.

Note to replace Project with the name of your project everywhere.

  • Create file ./config.ru
require ::File.expand_path('../config/environment',  __FILE__)
run Project::Application
  • Create file ./config/application.rb, if you use any observers, move them from environment.rb to this file
require File.expand_path('../boot', __FILE__)
require 'rails/all'
Bundler.require(:default, Rails.env) if defined?(Bundler)
module Project
  class Application < Rails::Application
    #config.active_record.observers = (move from environment.rb)
    config.autoload_paths += %W(#{config.root}/lib)
    config.encoding = "utf-8"
    config.filter_parameters += [:password]
  • Replace contents of ./config/boot.rb with
require 'rubygems'
gemfile = File.expand_path('../../Gemfile', __FILE__)
  ENV['BUNDLE_GEMFILE'] = gemfile
  require 'bundler'
rescue Bundler::GemNotFound => e
  STDERR.puts e.message
  STDERR.puts "Try running `bundle install`."
end if File.exist?(gemfile)
  • Create file ./Gemfile, taking note of the gems you currently include in ./config/environment.rb
source 'http://rubygems.org'
gem 'rails', '3.0.0'
#gem 'sqlite3-ruby', :require => 'sqlite3'
gem 'pg'
# gem 'aws-s3', :require => 'aws/s3'
# gem "will_paginate", "~> 3.0.pre2"
# gem 'fastercsv'
  • Replace contents of ./config/environment.rb with
require File.expand_path('../application', __FILE__)
  • Rework ./config/environments/development.rb
Project::Application.configure do
  config.cache_classes = false
  config.whiny_nils = true
  config.consider_all_requests_local = true
  config.action_view.debug_rjs = true
  config.action_controller.perform_caching = false
  config.action_mailer.raise_delivery_errors = false
  config.active_support.deprecation = :log
  config.action_dispatch.best_standards_support = :builtin
  • Rework ./config/environments/production.rb
Project::Application.configure do
  config.cache_classes = true
  config.consider_all_requests_local = false
  config.action_controller.perform_caching = true
  config.action_dispatch.x_sendfile_header = "X-Sendfile"
  config.serve_static_assets = false
  config.i18n.fallbacks = true
  config.active_support.deprecation = :notify
  • Rework ./config/environments/test.rb
Project::Application.configure do
  config.cache_classes = true
  config.whiny_nils = true
  config.consider_all_requests_local = true
  config.action_controller.perform_caching = false
  config.action_dispatch.show_exceptions = false
  config.action_controller.allow_forgery_protection = false
  config.action_mailer.delivery_method = :test
  config.active_support.deprecation = :stderr
  • Create file ./config/initializers/secret_token.rb
Project::Application.config.secret_token = '(copy from old session_store.rb)'
  • Rework file ./config/initializers/session_store.rb
Project::Application.config.session_store :cookie_store, :key => '(copy from old session_store.rb)'
  • Create file ./config/initializers/site_keys.rb
REST_AUTH_SITE_KEY = '(any moderately long, unpredictable text)'
  • Create file ./script/rails
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application',  __FILE__)
require File.expand_path('../../config/boot',  __FILE__)
require 'rails/commands'
  • Rework the file ./config/routes.rb
Project::Application.routes.draw do
  resources :users
  namespace :admin do
    resources :users
  match '/login' => 'sessions#new', :as => :login
  match ':controller(/:action(/:id(.:format)))'
  • Delete the file ./config/initializers/new_rails_defaults.rb
  • Update ./Rakefile
require File.expand_path('../config/application', __FILE__)
require 'rake'

Now, the fun starts. Update any gems and plugins as needed. The standard Rails forms used the error_messages method, you can either install the compatibility gem or rework the forms (recommended) like so:

Where you previously had:

<%= f.error_messages %>

insert this code:

<% if @product.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@product.errors.count, "error") %> prohibited this product from being saved:</h2>
      <% @product.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
<% end %>