before_save and after_save trouble when saving an associated object

Oct 17, 2008

New as of Rails 2.1.1 the before_save filter and the after_save filter stack has been modified. If you have to save the object associations again the after_save filter you can create the infinite loop of cpu love. Hence there needs to be some intervening step to keep it from looping.

SomeModel < ActiveRecord::Base

  ... 
  before_save :do_something 
  after_save :something_else 
  ... 
  def do_something
    self.manipulate 
  end 

  def something_else 
    self.association.manipulate 
    self.association.save 
  end 
end   

This worked up as above until rails 2.1.0, I would like to note that the above method although it worked, should not have used. Now you maybe wondering why I must do something else after and not before. The action I am taking requires data generated during the save. In order to keep things DRY, I allow the system to perform the necessary actions in the after_save so as to simplify the process. The way to deal with this is:

SomeModel < ActiveRecord::Base
  ... 
  before_save :do_something 
  after_save :something_else 
  ... 

As before the before_save is the same

 
  ...
  def do_something 
    self.manipulate 
  end
  ...

Instantiating a new object from the association out will bypass the manipulation of self, thus preventing the infinite loop of cpu love

	...
  def something_else 
    obj = self.association 
    obj.manipulate 
    obj.save! 
  end 
end 

The result is that rails doesn’t loop. If you should need to manipulate self in after_save, I would recommend, putting some conditionals in place that will bypass the before_save and after_save filters as necessary based on the changes or required data. One caveat is the ActiveRecord::Dirty will only work for unsaved content that has been saved. Once the object is saved, you loose that. It is better to check for the existence/ non existence of attributes to test as conditionals.

Posted by

Tags: rails