jefflunt
jefflunt

Reputation: 33954

Is there an existing solution in Rails, ActiveRecord, or a gem, for getting the timestamp of the latest change to any associated record?

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

Answers (2)

user229044
user229044

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

Wizard of Ogz
Wizard of Ogz

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

Related Questions