I’ve got a polymorphic association on one table. I assign to it in the
controller.
This is handling invitations of users to tasks in a task management
application. If the user issuing the invitation is the user being
invited (ie the user assigned themselves to a task), I want to
activate the invitation immediately in the model.
The trouble is that this:
if self.assignable == self.created_by
self.activated_at = Time.now
self.activation_code = nil
end
fails to detect equality correctly. I’ve tried ===, eql? etc.
When I look at .id when I know that I set assignable equal to
created_by, the values are different (wildly so; one is like 4 and the
other is a five digit number or something).
I’m guessing Rails handles polymorphic associations via a proxy object
or something. So the question is: how do I do this comparison?
You can get the underlying object from the proxy calling #target or
#proxy_target. That should allow you to compare the object ids
directly.
But why not compare the #id (eg, the actual primary key of the users
table) of both assignable and created_by. This is safer especially if
activerecord decides load created_by and assignable into two different
objects which is probably very likely.
On May 6, 9:54 am, eden li [email protected] wrote:
You can get the underlying object from the proxy calling #target or
#proxy_target. That should allow you to compare the object ids
directly.
But why not compare the #id (eg, the actual primary key of the users
table) of both assignable and created_by. This is safer especially if
activerecord decides load created_by and assignable into two different
objects which is probably very likely.
The problem with comparing just the ids is if the polymorphic
association is to a different table (ie to a different class), to an
object that happens to have the same id in that other table.
Unfortunate that if this is documented anywhere, it’s carefully
hidden.
Thanks.
On May 6, 9:54 am, eden li [email protected] wrote:
You can get the underlying object from the proxy calling #target or
#proxy_target. That should allow you to compare the object ids
directly.
This doesn’t work. Changing the code to:
if self.assignable.target == self.created_by
self.activated_at = Time.now
self.activation_code = nil
end
fails. As does using assignable.proxy_target.
Anyone know how to get this working?
On May 6, 5:46 pm, Gisborne [email protected] wrote:
self.activation_code = nil
end
fails. As does using assignable.proxy_target.
Anyone know how to get this working?
Whoops. Turns out it works fine and I was just being a complete moron.
Thanks for the help.
On May 7, 12:44 am, Gisborne [email protected] wrote:
The problem with comparing just the ids is if the polymorphic
association is to a different table (ie to a different class), to an
object that happens to have the same id in that other table.
Maybe I misunderstand your schema, but after retrieving “assignable”
you should get a proper user object. The polymorphic association will
retrieve the object from the right table for you. This is one of the
reasons you need an :assignable_type column.
Unfortunate that if this is documented anywhere, it’s carefully
hidden.
The association proxies are in the guts of ActiveRecord. I assume
it’s not well documented because rails-core wants to be able to make
massive changes to it between releases. Anyway, you only need to deal
with them if you’re relying on strict ruby object semantics.