I observed that a typical way of doing something in rails, if data-base related changes happen, is to use callbacks.

For eg: if you want to delete a phone, you need to remove all the apps installed in the phone.

In monolythic rails app, this is what folks do:

class Phone
  after_commit :delete_installed_apps, on: :destroy

This innocent looking code silently introduces a nasty pattern of doing things.

Everytime someone wants to do something when a phone is deleted, they’ll start adding after_commit methods.

class Phone
  after_commit :delete_installed_apps, on: :destroy
  after_commit :delete_user_data, on: :destroy
  after_commit :notify_app_dev, on: :destroy

The code smell here is that the class Phone knows about things to do after the phone is destroyed. It absolutely shouldn’t know this.

Another issue is that these procedural methods are executed one by one.

delete_installed_apps -> delete_user_data -> notify_app_dev

Exception raised in any one of them causes other methods to not execute.

When I faced this problem, I did the following to just get away with the problem.

def DeletePhone
  def execute(phone) 

This introduces the same pattern. The only difference here is that instead of putting it on the callback, we start putting it in the ensure block.

Coming back to the main problem, the code smell.

How can we get rid of the extra information in the Phone class? By sending an event.

If Phone’s object can send an event that it’s destroyed, then other objects could just listen to