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
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"?
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