0
votes

Callbacks on objects which are updated during removal from a relationship collection don't seem to be executing for me.

I have a model EntityLocation which serves as a polymorphic relationship between Entities (Users/Places/Things) and Locations (Zips, Addresses, Neighborhoods).

class EntityLocation < ActiveRecord::Base
  belongs_to :entity, :polymorphic => true
  belongs_to :location, :polymorphic => true

  def after_save
    if entity_id.nil? || location_id.nil?
      # Delete me since I'm no longer associated to an entity or a location
      destroy
    end
  end
end

For this example, lets assume that I have a "Thing" with a collection of "Locations", referenced by my_thing.locations. This returns a collection of Zip, Address, etc.

If I write the code

my_thing.locations = [my_thing.locations.create(:location => Zip.find(3455))]

then as expected a new EntityLocation is created and can be accurately referenced from my_thing.locations. However the problem is that the records which were previously contained within this collection are now orphaned in the database with a nil entity_id attribute. I'm trying to delete these objects in the after_save callback, however it's never getting executed on the old object.

I've also tried using an after_update, and after_remove and neither gets called on the old record. The newly created record after_save callback does get called as expected, but that doesn't help me.

Does Rails update the previously referenced object without executing the callback chain through active record? All ideas appreciated. Thank you.

1

1 Answers

0
votes

Why does this need to be polymorphic? It seems that you could simply use has_many :through to model the many-to-many relationship.

Secondly, why not simply delete the join table row through the association with :dependent => :destroy? Then you don't need a custom callback

class Entity < ActiveRecord::Base
  has_many :entity_locations, :dependent => :destroy
  has_many :locations, :through => :entity_locations
end

class EntityLocation < ActiveRecord::Base
  belongs_to :entity
  belongs_to :location
end

class Location < ActiveRecord::Base
  has_many :entity_locations, :dependent => :destroy
  has_many :entities, :through => :entity_locations
end

Now deleting from either side deletes the join table row as well.