Gotchas When Upgrading to Rails 2.1

Chad Pytel

We’ve upgraded several Rails 2.0 application to Rails 2.1 now, and we’ve compiled a list of little things to keep in mind as you upgrade. Hopefully this list will help you avoid banging your head against a wall.

Partial Updates

The updated_at and updated_on columns are NOT automatically updated on a #save on an AR object in Rails 2.1, unless another column has also changed. In each of the cases where we were relying on this behavior, we were using it to detect in a general way that something had changed with the model (without introducing a dependency on acts_as_modified). Because Rails 2.1 has dirty attribute checking, these methods were able to be refactored using this new functionality.

Will Paginate

Older versions of will_paginate are broken on 2.1 (stack level too deep errors), to resolve, install the latest version of will_paginate like this:

sudo gem install mislav-will_paginate -s http://gems.github.com

Then put require will_paginate in an initializer or in environment.rb (you need to have added vendor/gems to load path already to do that).

This newer will_paginate has changed the #page_count method to be #total_pages instead, so you’ll have to keep that in mind. Which means, some of the will_paginate view helpers changed as well – if you’ve monkey patched them (you haven’t unless you’re me!) look for changes there too!

Finally, Squirrel’s WillPagination module provides a #page_count method. To get a #total_pages from squirrel results, we temporarily monkey patched Squirrel by adding a lib/extensions/squirrel.rb which was just…

module Squirrel
  module WillPagination
    alias_method :total_pages, :page_count
  end
end

We’ll need to update Squirrel soon to have this built in so that its compatible with the latest version of will_paginate.

Shoulda

Make sure you’ve upgraded Shoulda if you get errors about not being able to find fixture methods and/or assert, especially if these errors appear in setup blocks.

HAML

Unfortunately, haml isn’t Rails 2.1 compatible. To fix this, upgrade to haml-2.0.

Reply-to in mailers

If you have the following hack in your mailer, just remove it. Rails 2.1 does it for you:

def reply_to(str)
  @headers["Reply-To"] = str
end

Changes in Active Record Attribute Filtering

ActiveRecord::Base#attributes does not allow filtering anymore (it does not accept :only, for example). You must do the filtering manually, with something like this:

def json_attributes_for(model, *attrs)
  attrs = [attrs].flatten.map(&:to_s)
  model.attributes.delete_if{|k,v| !attrs.include?(k) }.to_json
end

Called like so: json_attributes_for(page, :id, :keyword)

Changes in Template Rendering

Now in Rails 2.1, if you both foo.rhtml and foo.rxml exist and you aren’t explicitly specifying one or the other, Rails will render with foo.rxml. Renaming foo.rhtml to foo.html.erb fixes this, but in Rails 2.0, this was ok.

Relationship Optimized Eager Loading

In order to deal with the 1+n query problem, Active Record has changed how it does eager loading. Now, it will optimize out :includes on finders when they are not being used. When they are not being used is the key here. Active Record is supposed to noticed when there are additional conditions on the find that rely on the included table, and not leave it out.

However, on an association like this:

has_many :active_sites,
  :through => :clients,
  :source => :sites,
  :include => :domains,
  :conditions => 'domains.id IS NOT NULL'

Active Record leave out the domains table, even though it shouldn’t. We fixed this by changing active_sites to just a normal method, as the bug doesn’t seem to happen in find, like this:

def active_sites
  sites.find :all, :include => [:domains], :conditions => 'domains.id IS NOT NULL'
end

has_finder

has_finder has been integrated into Rails 2.1 as named_scope, so you don’t need it anymore. However, you also shouldn’t keep it around. For example, has_finder-1.0.5 was giving us stack trace too deep exceptions when traversing a has_many :through association. Removing it in favor of named_scope fixed that issue.

In Conclusion

Those are the things that we’ve found that we feel might be helpful to other people out there. For the most part, upgrading to Rails 2.1 is a a straightforward process, and we’re quickly upgrading most of our apps.

Have you upgraded to 2.1 and run into anything that other people might hit? If so, feel free to add your gotchas to the comments.