Things you should know about Rails Active Record callback, an AOP in other language

  1. Should avoid it when possible because its abstraction is not clear. The method such as after_save, before_save…etc. don’t have a clear purpose of the business logic rather than CRUD. It applies whenever before or after save active record object. Even you have conditional callback, it will exist in model or tight coupling with model itself. It probably better to have service class to do the work which has clear purpose of the business logic.
  2. If it is used it should be asynchronous, so that the main action like save or update request won’t rely on the the completion of the callback action. Use Sidekiq for example.
  3. Prefer after_commit to after_save, after_update, after_destroy because with after_save for example, the callback always execute no matter main action is execute successfully or not. With after_commit with on: option will tight with database transaction, this ensure that callback only execute when the transaction is complete. Another example using with asynchronous like Sidekiq dealing with id because without after_commit sidekiq might pickup id before object is committed to database.
  4. On the other hand to point 1, I debate callback vs service class. Rails active record callback has its own value. For example, if after_save: do_something is a must in any circumstance, we should use call back because new developer might not be able to cover up do_something in any adding new service class they create. More concrete example, if we want to destroy records in table A associated with table B when record in table B is changed, using callback might be a good option because if we have many service classes to trigger changing record in table A, we don’t need to modify all those service classes to destroy record in table A. If new developer create new interface or service class related to changing record in table B, they don’t have to know if they need to destroy record in table B because the callback in model say it all with test as well. However, if you are trying to use callback just in for specific logic rather than logic in model object, having service class is better option.
service class vs model

More best practice using callback in Rails: https://engineering.gusto.com/the-rails-callbacks-best-practices-used-at-gusto/