Reputation: 33954
Let's say I have:
class Foo < ActiveRecord::Base
has_many :bar
end
class Bar < ActiveRecord::Base
belongs_to :foo
end
Also assume that the Bar
class has timestamp fields (the ones that are automatically updated when the record is updated).
Question: Is there existing functionality/method calls in Rails, ActiveRecord, or a gem somewhere that allows me to call a method that will tell me most recent value in the updated_at
columns in any of the records, in any of the associations defined on the Foo
class?
So, a theoretical foo.latest_change_to_associated_objects
method should give me a timestamp of when the latest updated_at
field is for any of my associated records (in this case, for any Bar
record).
The simplest case, where you have a parent class and just one association is simple enough - a callback or two would do the trick. I'm curious about situations where a class has many associations defined. Is there a gem (or functionality already inside of ActiveRecord that I'm missing) that allows me to declare any/all of my associations to have this functionality?
Obviously I could do a SQL call to figure this out, but I don't want to do that every time I check for the latest change. It seems like there should be a callback chain the automatically updates a latest_change_on_association
field (or whatever you want to call it) on the parent when any associated record is changed, such that retrieving the latest change timestamp is a matter of checking a single field on the parent record.
Note: I looked into http://api.rubyonrails.org/classes/ActiveModel/Observer.html, but the problem there is that I'd have to write an observer for every class. It'd be great if the automation of creating the observers from a list of associations was already wrapped up in a gem or something.
Upvotes: 2
Views: 299
Reputation: 239240
You can use :touch
to automatically update the updated_at
timestamp (or any other timestamp field) of a parent record of a belongs_to
when one of its associated records changes:
Emphasis is mine:
:touch
If true, the associated object will be touched (the updated_at/on attributes set to now) when this record is either saved or destroyed. If you specify a symbol, that attribute will be updated with the current time in addition to the updated_at/on attribute.
If you really want to use your last_association_updated_at
column, you can:
belongs_to :parent_class, :touch => :last_association_updated_at
See the Rails Guide on Associations.
Upvotes: 2
Reputation: 12643
I would recommend adding a column to the table for the parent class which would hold the timestamp of the latest change. Let's call the column "last_association_updated_at". Then use the :touch
option on the association in each child class. Any time a child record is created, modified or deleted the last_association_updated_at
column will get updated with the current time.
class Foo < ActiveRecord::Base
has_many :bar
end
class Bar < ActiveRecord::Base
belongs_to :foo, :touch => :last_association_updated_at
end
class Baz < ActiveRecord::Base
belongs_to :foo, :touch => :last_association_updated_at
end
Upvotes: 1