one does not simply "upgrade to rails 3"

40
ONE DOES NOT SIMPLY UPGRADE TO RAILS 3

Upload: testflyjets

Post on 16-Apr-2017

1.021 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: One does not simply "Upgrade to Rails 3"

ONE DOES NOT SIMPLY

UPGRADE TO RAILS 3

Page 2: One does not simply "Upgrade to Rails 3"

Adventures in Upgrading From Rails 2 to 3

Chris McCann @testflyjets

github.com/testflyjets

Page 3: One does not simply "Upgrade to Rails 3"

The Task

Upgrade a Rails 2.3.5 app to Rails 3.1 Ultimately upgrade to Rails 4

Page 4: One does not simply "Upgrade to Rails 3"

Why?

Page 5: One does not simply "Upgrade to Rails 3"

Benefits to Upgrading

Security patches Ruby 2.0 New gems and capabilities, Bundler Asset pipeline + Sass Framework improvements, speed Improve test coverage (spoiler: easy!)

Page 6: One does not simply "Upgrade to Rails 3"

The App

First app I ever built

Started in 2007

Rails 1.2 initially

Upgraded to 2.3.5

2nd Edition

Page 7: One does not simply "Upgrade to Rails 3"

The App

!

Monkey-patched gems (mysql, geokit, DJ)

Lots of plugins

Prototype helpers...lots

Page 8: One does not simply "Upgrade to Rails 3"

The App

CSS mess

Homebrewed authentication

Page 9: One does not simply "Upgrade to Rails 3"

The App

163 models

167 controllers

> 1,000 view templates

12,500 users

Over $500,000 in non-profit transactions

Page 10: One does not simply "Upgrade to Rails 3"

Testing to the rescue!

Page 11: One does not simply "Upgrade to Rails 3"

Not so much

Page 12: One does not simply "Upgrade to Rails 3"

Resources for Upgrading

Episodes 225, 226, 227

Page 13: One does not simply "Upgrade to Rails 3"

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>

Page 14: One does not simply "Upgrade to Rails 3"
Page 15: One does not simply "Upgrade to Rails 3"

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)

Page 16: One does not simply "Upgrade to Rails 3"

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

Page 17: One does not simply "Upgrade to Rails 3"

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

Page 18: One does not simply "Upgrade to Rails 3"

UDT: Upgrade Driven Testing

Page 19: One does not simply "Upgrade to Rails 3"

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

Page 20: One does not simply "Upgrade to Rails 3"
Page 21: One does not simply "Upgrade to Rails 3"

“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

Page 22: One does not simply "Upgrade to Rails 3"

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)

Page 23: One does not simply "Upgrade to Rails 3"

ActionMailer failer

Page 24: One does not simply "Upgrade to Rails 3"

ActionMailer methods

Mailer methods changed:

create_* and deliver_* are gone

email = Mailer.confirm(user)

email.deliver!

@body[“instance_var”] to @instance_var

Page 25: One does not simply "Upgrade to Rails 3"

ActionMailer viewsMailer 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?

Page 26: One does not simply "Upgrade to Rails 3"

Routing changes

Page 27: One does not simply "Upgrade to Rails 3"

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’

Page 28: One does not simply "Upgrade to Rails 3"

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                                        

Page 29: One does not simply "Upgrade to Rails 3"

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

Page 30: One does not simply "Upgrade to Rails 3"

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”

Page 31: One does not simply "Upgrade to Rails 3"

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)

Page 32: One does not simply "Upgrade to Rails 3"

No more Prototype helpers

Page 33: One does not simply "Upgrade to Rails 3"

Prototype helpers removed

remote_form_for!

form_remote_tag!

link_to_remote!

remote_function!

Ajax form/links now done with remote: true

Page 34: One does not simply "Upgrade to Rails 3"

Prototype callbacks link_to_remote(dues.email_link, ! :url => send_notices_flight_dues_path(@flight, dues),! :before => "Element.show('spinner')",! :complete => "Element.hide('spinner')",! :method! => :post,! :confirm => confirm) ! ! ! link_to(dues.email_link, ! send_notices_flight_dues_path(@flight, dues),! remote: true, ! method: :post, ! confirm: confirm) !

Page 35: One does not simply "Upgrade to Rails 3"

Use jQuery for callbacks application.js!!$("*[data-spinner]")! .on("ajax:before", function(){ ! $($(this).data('spinner')).show(); ! })! .on("ajax:complete", function(xhr, status){ ! $($(this).data('spinner')).hide(); ! })!

Page 36: One does not simply "Upgrade to Rails 3"
Page 37: One does not simply "Upgrade to Rails 3"

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

Page 38: One does not simply "Upgrade to Rails 3"

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

Page 39: One does not simply "Upgrade to Rails 3"

ONE DOES NOT SIMPLY

UPGRADE TO RAILS 3

Page 40: One does not simply "Upgrade to Rails 3"

Adventures in Upgrading From Rails 2 to 3

Chris McCann @testflyjets

github.com/testflyjets