Search code examples
ruby-on-railsactiverecordhook

how to skip or call another model's hook in rails?


I have a logic like this:

# SomeModel
before_save :before_save_callback
def before_save_callback
  AnotherModel.find(..).update!(name: 'random text')
end

# AnotherModel
before_save :before_save_callback
def before_save_callback
  self.assign_attributes(name: 'random text')
end

There are 2 triggers that do the same update. However, if I do it like this, and update SomeModel, it will do the update 2x (before_save_callback in SomeModel and before_save_callback in AnotherModel). Is there a way where I can skip callback without using update_column as I only want to ignore this specific callback? Or maybe can I trigger before_save_callback of AnotherModel in SomeModel without actually saving any attributes? Thanks


Solution

  • You can get around model callbacks with transient attributes:

    # AnotherModel
    attr_accessible :skip_some_callback
    before_save :before_save_callback, unless: :skip_some_callback
    # ...
    
    # SomeModel
    def before_save_callback
      AnotherModel.find(..).update!(skip_some_callback: true, name: 'random text')
    end
    

    But this pattern can quickly turn into a callback hell and for complex cases you can better organize your code into more high-level patterns like service objects, interactors, factories etc.