Forum: Ruby on Rails Is there a "touch" method for associated records?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A24e589de07cb769a71f28aead957a48?d=identicon&s=25 Duane Morin (dmorin)
on 2009-01-27 17:42
I'm sure I can whip something up to do this, but I'm wondering an
elegant solution already exists.  I will have any number of Registration
objects coming in through web form, but I wish there to be only one User
object per unique email address.  So far this works fine.  So
Registration belongs_to User, User has_many Registrations.  (This, by
the way, is because the site does not have a persistent profile/logged
in session and thus the same person could fill out the registration form
multiple times.)

What I'd like is if a person comes in a second time, creates a
Registration object using an email address that already has an
associated User, then update the User.updated_at field.  In other words,
the clean/dirty status of User is based on the most recent Registration
object that was added.

Does such a feature already exist in the association?  I figure I could
get around it altogether by defining User.updated_at as the max of
registrations.updated_at, but that's pretty inefficient.  My other
option is just to put in some sort of before_save filter on
Registration.  But it seems better placed on User - but User isn't
technically changing during this operation, right?  So I'm not sure
where I'd hook in.
2a39aed820c125e6db9826fa8180043f?d=identicon&s=25 Denis Haskin (Guest)
on 2009-01-27 18:35
(Received via mailing list)
I can see why you'd want to do this, but I'd leave User.updated_at alone
and track this 'dirtiness' in some other way.

There's no reason you can't do it, but as you say you'd have to
accomplish it with an AR callback on Registration, not User.

The default way automatic timestamping is implemented in AR implies that
the semantics of the updated_at timestamp are when the object *itself*
was updated.  If you change this behavior, you run some risk of a future
developer (or yourself in the future) not realizing that updated_at
*also* means the user's registrations had changed.  (As you said: "but
User isn't
technically changing".)  You also then lose the ability to know when the
User object itself was changed, as opposed to the list of registrations
(but maybe you don't need to be able to make that differentiation).

If I were convinced I needed to do it this way, I would probably add a
method User#registrations_changed and have the Registration callback
call that, so that this behavior is explicit (and, as you desired,
visible in the User class).  And would this be better on after_save, not
before_save?

And what events in the association would update the user?  Adds,
deletes, modifies?

My approach on this would also depend on why I needed to have the user's
update date be updated like this; how are you going to use that fact,
and could it be done by coming into the association via registrations?
E.g. "show me the users whose registrations changed yesterday" could
still, I think, be done fairly efficiently even without what you're
proposing.

dwh
A24e589de07cb769a71f28aead957a48?d=identicon&s=25 Duane Morin (dmorin)
on 2009-01-27 19:40
Thanks, Denis.  The project in question is actually a periodic email
pull for marketing purposes, which is why I'm taking pains to model a
"one email per user" expectation, something that current project does
not have. (I'll work them into an actual login/password protected
profile later...)  The reason that the updated_at is important is the
nature of the marketing message, which will be one of those "Since you
visited the site 2 days ago...." sorts of things.  If a user registered
for the first time (and created a User object) 3 days ago, but then came
back in today, registered again (and thus linked to but did not create a
User object), I would not want to send that message to that person.
So I need some way to touch the User object at each registration.

I think the option to create a different dedicated field on User, like
maybe last_registered_at, works best - it clearly defines the meaning of
the field for the next developer who comes along.

D


Denis Haskin wrote:
> I can see why you'd want to do this, but I'd leave User.updated_at alone
> and track this 'dirtiness' in some other way.
>
> There's no reason you can't do it, but as you say you'd have to
> accomplish it with an AR callback on Registration, not User.
>
> The default way automatic timestamping is implemented in AR implies that
> the semantics of the updated_at timestamp are when the object *itself*
> was updated.  If you change this behavior, you run some risk of a future
> developer (or yourself in the future) not realizing that updated_at
> *also* means the user's registrations had changed.  (As you said: "but
> User isn't
> technically changing".)  You also then lose the ability to know when the
> User object itself was changed, as opposed to the list of registrations
> (but maybe you don't need to be able to make that differentiation).
>
> If I were convinced I needed to do it this way, I would probably add a
> method User#registrations_changed and have the Registration callback
> call that, so that this behavior is explicit (and, as you desired,
> visible in the User class).  And would this be better on after_save, not
> before_save?
>
> And what events in the association would update the user?  Adds,
> deletes, modifies?
>
> My approach on this would also depend on why I needed to have the user's
> update date be updated like this; how are you going to use that fact,
> and could it be done by coming into the association via registrations?
> E.g. "show me the users whose registrations changed yesterday" could
> still, I think, be done fairly efficiently even without what you're
> proposing.
>
> dwh
This topic is locked and can not be replied to.