Question

I have a self-referential relationship and a has_many_through association set up with a model called "Item". I'm using touch on the "join model". My issue is that when I "tag" a child object, the parent isn't "touched" even though there is a touch "chain" in place that to my mind should update the parent.

# the model

class Item < ActiveRecord::Base
  belongs_to :parent_item, class_name: 'Item', touch: true, inverse_of: :children_items
  has_many :children_items, class_name: 'Item', inverse_of: :parent_item
  has_many :taggings, inverse_of: :item
  has_many :tags, through: :taggings
end

class Tagging < ActiveRecord::Base
  belongs_to :tag, inverse_of: :taggings, touch: true
  belongs_to :item, inverse_of: :taggings, touch: true
end

class Tag < ActiveRecord::Base
  has_many :taggings, inverse_of: :tag
  has_many :items, through: :taggings
end


# the behaviour

item = Item.create!
child_item = item.children_items << Item.new

# before tagging
before_tagging_time = item.updated_at
# tagging the child
child_item.tags << Tag.new(name: "unimportant")

# after tagging
item.updated_at == before_tagging_time # => true

Is this a bug?

I would expect the last line to evaluate to false, but it evaluates to true. That is, I'd expect adding a Tag to a child Item where tags and Item both have touch on all belongs_to relationships to trigger the touches on that model, but it doesn't seem to behave in this way.

Is this a case of me not understanding intended behaviour of this feature? Should I be using an after_touch callback?

My expected behaviour is that touches count as saves... do I need to manually add an "after_touch" callback to each of my models which touch so I can get the expected behaviour of a "touch chain"?

Was it helpful?

Solution

Your "touched chain" should work. Reload the Item record and you should see the correct value for updated_at.

item.reload.updated_at == before_tagging_time # => false

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top