Tuesday 14 July 2015

Choose the right call backs in rails. (an example by comparing after_create and after_commit)


 We get into the situation where incident object need to created/saved with before_save and after_create/after_commit.  
 first attempt [ incident object with before_save and after_create]  
 incident have an attribute called status.  
 before_save  
 def build_incident_logs  
    self.event_logs.build if status_changed?  
 end  
 incident object  
 incident.save  
 after_create  
 def update_attribute_of_incident  
    self.attribute_one = value    
    binding.pry  
    self.save!  
 end  
 a.Start the server begin the process, first it comes to before save and build the incident logs.  
 b.Then incident will be created.  
 c. After create is called and while trying to update attribute of incident, before save is called again. Now code inside before_save look for status changes.  
 4. All this happen inside same transaction.  
 5. So self.id_was nil. Again it will create an duplicate data in incident logs  
 I have attached the screen shot of this for better understand.  
 
Second attempt [ incident object with before_save and after_commit] Now change after_create to after_commit before_save def build_incident_logs self.event_logs.build if status_changed? end incident object incident.save after_commit def update_attribute_of_incident self.attribute_one = value binding.pry self.save! end a.Start the server begin the process, first it comes to before save and build the incident logs. b.Then incident will be created. c. After create is called and while trying to update attribute of incident, before save is called again. Now code inside before_save look for status changes. 4. Because of after_commit, it will start the new transaction and previous transaction was closed. 5. Status is available. 6. If i request for self.id_was some_id (eg:34). so no duplicate data is created at incident logs.
Conclusion: Above content will helpful to pick the right call backs based on requirement. after_create will look into same transaction but after_commit will begins from new transaction .