Upgrading a Rails 2.2.2 app to Rails 3
Posted by Jim Morris on Fri Dec 17 15:27:17 -0800 2010
After porting my blog engine from Merb to Rails3 code here I thought I'd upgrade my Snow Dogs R Us Site (aka dogz.us) to Rails 3.
It was written in Rails 2.2.2 so I figured it would not be too hard, well it was easier to port my Merb App than it was my Rails app!
Most of the issues were related to plugins currently not working with Rails 3, and having to find equivalent ones and port to them, so to be fair the actual change from Rails 2 to Rails 3 was not that hard, but fixing several of the plugins was a pain.
First I followed several blogs the most useful being this one.
That got most of the mundane stuff done. Especially using the upgrade plugin helped.
Then the plugins had to be upgraded, several do not seem to have been
updated by the original owner so I had to point to several other git
repos, it is easy if they are on Github, use the network tool and pick
the latest one and see if they have a rails 3 branch. Several of the
plugins I was using are now gems, so I just added them to my Gemfile
and removed them from vendor/plugin
,
I was using calendar-date-select
but switched to using JQuery date
select instead and the new Unobtrusive JavaScript pattern. I had to
add the jquery-ui-timepicker-addon
to get data and time selected in
one input field.
I also was using will-paginate
, but switched to just previous and
next links. Although will-paginate
has a Rails 3 version
gem 'will_paginate', '3.0.pre2'
I was using cssFormBuilde
r, which no longer appears to be supported so
I switched to simple_form
which meant going through all my forms and
changing them, but ended up with a pleasant result.
acts-as-taggable(-on steroids)
does not seem to have been updated to
Rails 3 so I switched to acts-as-taggable-on
which required minimal
changes.
acts-as-commentable
has been upgraded and I just needed to switch to
the gem version.
attachment-fu
was the biggest pain, it no longer works on Rails 3,
and the repos I tried that supposedly had fixed them did not work for
me, so I switched to
paperclip, which works fine
with Rails 3, and there are a few
blogs
showing how to upgrade from attachment-fu
to paperclip.
I wrote this little script to copy the files over from attachment-fu
to paperclip
...
and here is the migration...
I needed a few plugins...
rails plugin install git://github.com/rails/dynamic_form.git
rails plugin install git://github.com/rails/verification.git
Just so I didn't have to change too much these are mostly compatibility
plugins. However after getting everything working I removed the
dynamic_form
plugin and switched to simple JQuery UJS techniques to
handle the remote calls.
The other big pain that was a lot of work is the new auto escaping of
text in Rails Views. I already had used h()
on all user inputs, but
now most of my view helpers were broken because they did not generate
html_safe
strings. The fix was either to use !=
in my HAML views
(!=
in HAML will print the result raw with no escaping) so
it would override the escaping, or use String#html_safe
in my helpers
to mark my strings as safe.
A few of my plugins continued to work fine with very minor fixes like
acts_as_rated
used class_name
to get the name of a class in
ActiveRecord, but that has been removed so I used base_class
in the
two places it was used. I fixed it in my clone of the
plugin and issued a Paul
request, which I believe has been accepted.
The auto_complete
plugin doesn't work out of the box either, probably
because inline javascript is frowned on now and unobtrusive javascript
is all the rage. There is a git repo which supposedly fixes it for
Rails 3, and it does work except you need to html_safe
the strings it
returns. (or use !=
in haml).
rails plugin install git://github.com/fcioffi/auto_complete.git -r rails3
is what you need to do to use this.
However after getting it to work, I deleted it and switched all my
uses of auto_complete
to use the
JQuery based
autocomplete. Which worked pretty well with a little tweaking here and there.
I had to look at the source code to determine that if I wanted to get
multiple autocompletes using a comma I had to add
'data-delimiter' => ','
to the form input.
The most work was getting all my specs to pass, apart from minor changes to the application itself, RSpec 2 has changed quite a lot, and updating my specs to work with RSpec 2 requires a lot of tedious work:-
needed to rename all my views from
.haml
to.html.haml
, (or.html.erb
) although Rails 3 seemed OK with the old naming RSpec2 view specs failed to find the templates with the old name.rewrite all my view specs...
change
...@controller.template.
toview.
change
have_tag
tohave_selector
and change the parameters- place holders not supported, need to use #{}
- add :content => for any text in second parameter
- could also use have_xpath, which allows things like have_xpath('//a', :href => "/post/#{post.id}/edit", :content => 'Edit')
change
assign[:blah]= :blod
toassign(:blag, :blod)
change the describe "a descripion" do to have the path to the view rather than text description describe "events/show.html.haml"
change the render '/show' to just render or render :file => 'full template spec'
change have_text to match(/../)
change response.should to rendered.should
modify the controller specs
controller_name is no longer supported, so need to nest all my describes under a top level describe that has the controller name. describe 'UsersController' do or use subject {SomeController.new} (not tested yet)
when using post/delete/put :something, :id => 1 passing in an integer id used to work, now it needs to be a string (probably a rails3 thing) delete :destroy, :id => "1"
helper specs only needed minor changes
- change
have_tag
tohave_selector
orhave_xpath
- change
After all this the specs passed and the app was updated to use JQuery and UJS, however I had a few DEPRECATION warnings some of which were hard to track down...
To get rid of these deprecation warnings...
DEPRECATION WARNING: "Rails.root/test/mocks/development"...
DEPRECATION WARNING: "Rails.root/test/mocks/test"...
Just delete the test/mocks directory.
So for a fairly small Rails app of around 5 KLOC it took about 10 days to fully upgrade to Rails 3, switching over to UJS everywhere and fix the specs.
To be honest I don't think it was worth the effort, but it was a great learning experience, and I had the free time! and now I know all about Rails 3.
Wow yeah so I *just* made a git branch to try to upgrade my rails 2.2.2 app to 3.0 and you confirmed my biggest fears.. it's not gonna be worth it.. I too use attachment_fu but even bigger of a pain in the ass is that I'm using engines which is probably gonna be another nightmare to untangle to work with rails 3... man... this sucks but at some point I'll have to bite the bullet and upgrade because of security patches.
act-as-taggable-on-steroids did update to Rails 3. If you use act-as-taggable-on, you are going to have issues with the "context" column added in it, that was not present in the steroids one. If you already had a database populated with tags created based on the steroids one, you are going to have problems. At least I guess that the "not steroids" one has a caching that works, because in steroids one I never got it to work.
I had to use the following migration to covert
class AddTaggableOnColumns < ActiveRecord::Migration
def self.up
add_column :taggings, :tagger_id, :integer
add_column :taggings, :tagger_type, :string
add_column :taggings, :context, :string
add_column :taggings, :created_at, :datetime
remove_index :taggings, [:taggable_id, :taggable_type]
# we need to set the context for exisiting tags
execute "UPDATE taggings SET context = 'tags'"
add_index :taggings, [:taggable_id, :taggable_type, :context]
end
def self.down
remove_index :taggings, [:taggable_id, :taggable_type, :context]
remove_column :taggings, :tagger_id
remove_column :taggings, :tagger_type
remove_column :taggings, :context
remove_column :taggings, :created_at
add_index :taggings, [:taggable_id, :taggable_type]
end
end