A talk given at the February SD Ruby meeting in San Diego, covering the issues one might face when upgrading a Ruby on Rails application from version 2.3 to 3.2.
Covers items deprecated or eliminated between versions, testing strategies, pain points, gotchas and general suggestions for making the transition across major versions of the Rails framework.
13. My Hybrid Approach*
Create a new Rails 3 app
Install Rails 3 versions of gems, replace plugins
Get the framework running with config from old app
The first goal is to get to:
* Thanks to Rob Kaufman @ Notch8
$ rails console !
$ irb(main):001:0>
14.
15. MySQL
Originally MySQL 5.1 + mysql gem + monkey patch
Not compatible with Rails 3 >> MySQL 5.5 + mysql2
Broke original app on dev machine because it can’t use
MySQL 5.5 (bad handshake, disconnect errors)
Solution: live with it (have 2nd dev machine)
16. Plugin > gem conversion
Generally not too terrible
Most plugins available as Rails 3 gems
Can still use vendor/plugins if necessary
Spoiler alert: you won’t find all the problems initially
17. Framework configuration
Custom configuration code moved from
environment.rb to application.rb
Initializers used extensively in Rails 3
autoload paths (like /lib) need to be specified
parameter filtering (passwords, credit card numbers)
now in application.rb not in controllers
Solution: just gut it out until things work
19. Tests as sanity checks
Try to rapidly touch every model to trigger failures
Tools of choice: rspec, factory_girl, spork, faker
Script to generate specs and factories for all models:
rails generate rspec:model #{model_file} -s
20.
21. “Canary in a coal mine” tests
I didn’t find a quick way to check my models
Specs you don’t write are all “pending”
Hidden land mine: attr_accessible
22. Model changes everywhere
named_scope became scope plus syntax changes
(deprecation)
validates_* to validates (*attributes)!
Had to update for rspec matchers to work
ActiveModel find syntax changes (deprecation)
24. ActionMailer methods
Mailer methods changed:
create_* and deliver_* are gone
email = Mailer.confirm(user)
email.deliver!
@body[“instance_var”] to @instance_var
25. ActionMailer views
Mailer views renamed:
*.text.html.erb to *.html.erb
*.plain.text.erb to *.text.erb!
*.rhtml is completely deprecated, will fail
Solution: easy to test them, trigger failures, fix ‘em
Gotcha: links in your emails? How’s your routes.rb?
27. Joys of RESTful routing
Original app had mix of RESTful and controller/action
Bad, bad, bad: Catch-all route
map.connect ‘:controller/:action/:id.:format’
28. Routing syntax tedium
flight.resource
:roster_import,
:controller
=>
:import,
:only
=>
[:new,
:create],
:member
=>
{
:import_csv
=>
:get,
:import_setup
=>
:get,
:match_imports
=>
:get
}
!
resource
:roster_import,
controller:
'import',
only:
[:new,
:create]
do
member
do
get
'import_csv'
get
'import_setup'
get
'match_imports'
end
end
29. Controller Testing
Hoped for a straightforward way to sanity check
request specs vs controller specs?
rspec let() vs @var : association issues
Bottom line: steep learning curve but necessary
30. Asset Pipeline
Asset Pipeline partially implemented already
Managed to double-include some files
Watch out for relative paths between JS and CSS
Overall: not terrible, probably easier without “poor
man’s pipeline”
31. View booby traps
Views can be a pain to test
Over 1,000 view templates in the app
ERB changes to look for:
<% form_for ...%> to <%= form_for ...%>!
Using raw to escape HTML built in strings (helpers)
37. Geocoding and GMap
Used geokit, monkey-patched for exception handling
during auto-geocoding
Google killed GMaps v2 last fall
New geokit-rails for Rails 3: used v2, no “distance” field
Solution: replace geokit-rails with geocoder
38. tl;dr
Upgrading between major versions is hard
Not having tests makes it MUCH harder
Incremental upgrade is way easier
For a large project, it simply takes time and effort
Retrofit tests as you go -- you’ll need them someday