I recently had to upgrade an old app and it went pretty smoothly so I thought I’d share how I did it.
I thought about two approaches to this upgrade
I could slowly add modernity to the existing app by adding bundler, upgrading rails, upgrading rspec, etc.
I could create a new Rails 3.1 project and copy the code and specs into this new project.
I downloaded the old code and immediately remembered the pain of getting an app up and running without bundler. This convinced me that #1 would be harder than it needed to
be so I decided to go with approach #2. It worked out pretty well so I’m going to share exactly what I did.
Create a new Rails 3.1 project
Add gems from my app
Because the old app comes from the days before bundler I had to look in config/environment.rb for lines like config.gem 'atom' and guess what else I needed (I knew I was using rspec).
Now we can make sure our empty app works (even though it does nothing)
Add our existing code and specs
Now when we try to run the specs it tells us we have pending migrations so we run them
Now we’re getting some errors and are ready to get to work.
Update our code
Of course it doesn’t just work and we need to make a number of changes. The guides include an upgrade process section
and the rails_upgrade plugin can help identify problems. Here are the ones I found.
Changing named_scope to scope
With Rails 3 the syntax for scopes changed from named_scope to scope. So we search-and-replace in our models.
Once we do this the specs run, but many are failing. A lot are failing because the routes.rb syntax changed in Rails 3.
RAILS_ROOT => Rails.root
The constant RAILS_ROOT no longer exists so we need to search-and-replace that with Rails.root.
We change it to:
RSpec Routing Specs
We have a bunch of routing specs that are failing because RSpec changed the syntax around routing specs.
The routing spec must be in folder called routing
Another syntax change in RSpec from using stubs to stub!
We get an error undefined method 'stubs' for \#<Feed:0x105d572e8>
Hmm I’m surprised I had written view specs. Nowadays I would write cucumber features and never write view specs.
That being said there were a few things I needed to change to get the view specs passing, all related to RSpec syntax changes.
I was passing @ variables to the view with assigns[:feed] = @feed = stub_model(Feed) and today you need to do that with assign(:feed, @feed = stub_model(Feed).
Also when you call render "/feeds/edit.html.erb" it used to work but now tries to render a partial. Plain old render will work as long as you’ve put
the filename in your describe like describe "/feeds/edit.html.erb" do
Deploying to Heroku
The old app was deployed to a VPS using Capistrano. Today I prefer to use Heroku and there were a few changes I had to make to get it working there.
Add pg to my Gemfile to support Postgresql
Configure assets (since we cannot write to the filesystem)
** Added config.assets.compile = true in my production.rb
** Added therubyracer to my Gemfile
Delete my old Capfile
Now I was able to deploy to heroku and the new app is up and running. All this done in less than a day!