Sohan's Blog

Living the Developer's Life

Are ActiveRecord Callbacks Any Good?

Wanted to share my thoughts on ActiveRecord Callbacks. I’d like to know your thoughts if you disagree. Please use the comments.

  • Only use them when the behavior is must have under all situations, including your tests. For example, we know email addresses are case-insensitive. So no matter what, we may always want to store a lower cased version in the db.
user.rb
1
2
3
4
5
6
7
8
9
10
#Good
class User < ActiveRecord::Base

  before_save :downcase_email

  def downcase_email
    email.downcase!
  end

end
  • Never use them otherwise. A couple of classic examples that I consider as bad:
user.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#Bad: Sends email, probably not required under all situations such as when creating via migrations, tests etc.
class User < ActiveRecord::Base

  after_create :welcome

  def welcome
    WelcomeMailer.welcome(self).deliver
  end

end

#Bad: Interacts with external components
class User < ActiveRecord::Base

  after_create :setup_orientation

  def setup_orientation
    OrientationMessageQueue.enque(self)
  end

end
  • A common problem with the callbacks is, there are some handy methods that skip the callbacks. For example, consider the following:
User.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#Careful

class User < ActiveRecord::Base

  before_save :update_coordinates

  def update_coordinates
    self.coordinates = Geo.find_coordinates(zip_code)
  end

end

#works fine
sohan = User.find_by_name('Sohan')
sohan.zip_code = '33333'
sohan.save!

#doesn't fire the callback
User.update_all({zip_code: '33333'}, {zip_code: '55555'})

If you’re using the callbacks, I’d emphasize again, only use when you are absolutely sure the desired behavior applies under all contexts.

Comments