Ruby, Ruby on Rails

Around callbacks in ActiveRecord

Callbacks are methods that get called at certain moments of an object’s life cycle. If you’re wondering why the above sentence sounds so coherent, its because I stole it verbatim from the Rails Guides.

So most people are pretty familiar with before and after callbacks. before_save and after_update pretty much explains itself. There is another type of callback though, called around.

What in the world does it do?

What it does is it allows you to run code both before and after an operation. So an example will be like this:


class Facility < ActiveRecord::Base
  
  around_save :method_around_save
  
  private 
    def method_around_save
    # you can do stuff here
      yield <---- the save happens here
    # you can continue doing stuff here as well
    end
end

So why is this useful? Whats the difference between this and doing 2 separate before_save and after_save callbacks?

In my opinion, the around callback could be useful if you want all your database transactions in your callbacks to be atomic.

Or if you want whatever you’re doing in after_save depends on what happens before_save

Lets have a concrete example, based on a make-believe real life scenario

Say you have a Building model, which has a number of facilities under it.
Every time a building is created, you want to create a set number of hardcoded facilities.

  class Building < ActiveRecord::Base

  has_many :facilities

  after_create :create_facilities
 
  def create_facilities
    #Do facility creation here
  end
end

So each facility, will have a number of sub-facilities (Just like how badminton courts have Court A, Court B, etc). These sub-facilities are also created when the a facility is created

class Facility < ActiveRecord::Base
  after_create :create_subfacilities

  def create_subfacilities
    # sub-facilities will be created here.
  end
end

So this looks ok, I guess. But what if someone updates the facility? Maybe the user made a mistake and set the number of sub-facilities to 2 when actually there were 3 sub-facilities?

One way is to do a check before the update happens to see if the number of sub-facilities has changed (before_update) and then update the sub-facilities after the facility has been updated (after_update)

Something like this maybe?

class Facility < ActiveRecord::Base
  after_create :create_subfacilities
  before_update :check_for_subfacility_change
  after_update :sync_subfacility

  def check_for_subfacility_change
    @sync? = true if #subfacility has been changed
  end

  def sync_subfacility
    #update number of sub-facilities based on the value of @sync?
  end

  def create_subfacilities
    # sub-facilities will be created here.
  end
end

I’m just guessing here, but perhaps this could be a bit difficult to read after a few months and when the class gets bigger. So it could be easier if we did the whole thing in one around_update callback.

Perhaps something like this

class Facility < ActiveRecord::Base
  after_create :create_subfacilities
  around_update :sync_subfacility

  def sync_subfacility
   sync? = true if #subfacility has been changed
   yield
   #update sub-facilities if sync? is true
  end

  def create_subfacilities
    # sub-facilities will be created here.
  end
end

So there you go, hopefully that made sense. If you can think of a better way please reply in the comments

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s