Search code examples
ruby-on-railsactiverecordruby-on-rails-5associations

Rails: Determine if attribute on association just changed


We have a Zoo model that has_many Animals. The Zoo model has:

after_commit :update_animals

def update_animals
  animals.each(&:do_update_animal)
end

The Animal model (which belongs_to a Zoo) in turn has:

def do_update_animal
  # here we need to determine whether the `self.zoo.zookeeper` attribute just updated
end

Inside of the Animal#do_update_animal block, how can we tell if the zookeeper attribute on the instance of Zoo associated with the Animal just updated?


NB: To get this working, I needed to change my has_many block on Zoo so as to indicate that Animal is the inverse_of Zoo--without that declaration, the dirty API did not work. So inside of Zoo I needed:

has_many :animals, inverse_of: :zoo

Solution

  • Try this:

    # zoo.rb
    after_commit :update_animals
    
    def update_animals
      animals.each { |animal|
        animal.do_update_animal
      }
    end
    
    # animal.rb
    include ZookeeperConcern
    
    # zookeeper_concern.rb
    def do_update_animal
      if zoo.zookeeper_previously_changed? # presumably animal belongs_to :zoo, right?
        # do something
      else
        # do something else
      end
    end
    

    This uses the ActiveModel::Dirty feature.