Hidden Secrets of the Rails Dev: Gotchas While Migrating from 2 to 3
Upon migrating from Rails 2 to 3, one might happen across some “gotchas”. I present a few such that you may heed caution.
ActiveSupport::Callbacks#run_callbacks
This method takes a &block parameter. In Rails 2, &block will run after each callback, and halt the chain if it returns false. In Rails 3, &block will run after the :before/:around callbacks and before the :after callbacks. More has changed about callbacks, so please read the docs.
Mail#header
ActionMailer in Rails 3 uses a different underlying library than 2: mail instead of tmail. Setting headers in the new library will accumulate headers rather than replacing them:
m['X-Something'] = 1
m['X-Something'] = 2
m.header['X-Something'] = 3
Now m has 3 values for the X-Something header: 1, 2 and 3.
ActiveRecord::Base#touch
In Rails 2, touch() ultimately calls save!() and runs through all the validation and callbacks. In Rails 3, touch() saves the record using update_all(), so no validations are performed and only the new after_touch() callback is run.
ActiveRecord#order
In Rails 2, queries are ordered like this:
User.first(:order => "name")
In Rails 3, AREL gives us a new method for queries called order(), but remember that it will accumulate order values instead of replacing them:
User.order("name").order("id").first
# ... ORDER BY name, id .... #
Remember to use reorder() to reset the value:
User.order("name").reorder("id")
# ... ORDER BY id ... #