Upgrading to Rails 3: Obstacles and helper scripts
Transferring an existing project to Rails 3 is not that hard, but it usually cannot be done in 5 minutes.
General upgrade approach
- Get the rails_xss plugin and adjust your
raw
helper calls till everything is fine again. - Check, if your plugins work at railsplugins.org.
- Get information about the changes and install the official rails_upgrade plugin. Run
rake rails:upgrade:backup
to backup important files. Then runrake rails:upgrade:check
to analyse your project. The plugin displays useful information for various places where things need to be changed. It also has tasks for creating yourGemfile
, updating your routes and configuration. But there is still some manual work required. I have written three little helper scripts that can assist you to solve some tasks. - When finished, replace some of the project’s Rails-specific files. You can do this by navigating to your project’s parent directory and running
rails my_project_name
as if you would want to create a new one. Then pick the files to overwrite.
Upgrade scripts
ERB syntax changes (the upgrade tasks complains about more, but this is wrong)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
#!/usr/bin/env ruby # Upgrades all files in child directories to the new erb snytax in Rails 3 # Does not upgrade custom concatination helpers # See <https://asciicasts.com/episodes/208-erb-blocks-in-rails-3> for more info patterns = %w| fields_for form_for div_for content_tag_for field_set_tag form_tag remote_form_for form_remote_for form_remote_tag | # don't forget to update remote helpers to hash option: remote => true Dir['**/*.*'].each{ |filename| data = File.read filename File.open(filename,'w'){|f| f.print data.gsub(/<%\s+(#{ patterns*'|' }).*(do|\{)/){ $&.sub '<%', '<%=' } } } puts :Done
Add the config initializer to environment files
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#!/usr/bin/env ruby # add the AppName::Application.configure command to all config/environments/* files ENVIRONMENTS_PATH = 'config/environments/' APPLICATION_PATH = 'config/application.rb' if !File.exist? ENVIRONMENTS_PATH raise 'Please call the script from the Rails root directory' elsif !( File.exist?(APPLICATION_PATH) && ( File.read(APPLICATION_PATH) =~ /module\s+(\w+)/ ) && $1 ) raise "You need an already updated #{APPLICATION_PATH} to run this script" else app_name = $1 Dir[ENVIRONMENTS_PATH + '*'].each{|filename| lines = File.readlines filename unless lines.join =~ /#{app_name}::Application.configure/ lines.map!{|l|' ' + l} lines.unshift "#{app_name}::Application.configure do" lines << "end" File.open(filename,'w'){|file| file.print lines.join } end } puts :Done end
Updade cookie secret store
(the syntax gem really sucks…)
#!/usr/bin/env ruby
# Upgrades the session store. Only run this script, if you use cookies for
# session storage.
#
# This script is quite destructive and uses eval, so please check if
# your config/initializers/session_store.rb file looks like this:
#
# ActionController::Base.session = {
# :key => ‘_app_session’,
# :secret => ‘secret’
# }
#
# Please upgrade manually, if you have changed more than the values
SESSION_PATH = 'config/initializers/session_store.rb'
SECRET_PATH = 'config/initializers/cookie_verification_secret.rb'
if !File.exist? SESSION_PATH
raise 'Please call the script from the Rails root directory'
else
# get data
old = File.read SESSION_PATH
if matched = old =~ /ActionController::Base.session\s+=/
old[/ActionController::Base.session\s+=/] = ''
user_data = eval old
end
if !matched || !user_data.is_a?(Hash)
raise "#{SESSION_PATH} has changed too much, aborting..."
end
# write new files
File.open(SECRET_PATH,'w'){|file|
file.puts "Rails.application.config.secret_token = '#{user_data[:secret]}'"
}
File.open(SESSION_PATH,'w'){|file|
file.puts "Rails.application.config.session_store :cookie_store, :key => '#{user_data[:key]}'"
} if File.exists? SECRET_PATH
puts :Done
end
Subtleties I had to deal with
Uninstall rails_xss
ActionView::Template::Error (undefined method `append=' for #<ActiveSupport::SafeBuffer:0xb6e2e4cc>)
rails_xss is a Rails 2 plugin. Remove it after the upgrade.
Controller’s initialize method
After the upgrade, my views suddenly did not have any layouts, anymore! This was caused by overwriting the initialize
method of a controller. Allowed in Rails 2, forbidden in version 3.
Add standard gems to Gemfile
In Rails 3, you need to put gems like sqlite and mongrel in your Gemfile
, or they will not be used:
gem "sqlite3-ruby", :require => "sqlite3"
gem 'mongrel'
Upgrade thin
/home/jan/.rvm/gems/ruby-1.8.7-p249/gems/activesupport-3.0.0.beta3/lib/active_support/dependencies.rb:209:in `require': no such file to load -- dispatcher (LoadError)
thin-1.2.5
is too old ;).
cache_template_loading
I had to remove this line from my config/environments/production.rb
:
config.action_view.cache_template_loading = true
Rails 3 Documentation
Rails 3 is updated almost every day and so do the docs change – so I relaunched PlasmaRails.org. It fetches Rails every day and generates its rdoc.