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.
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.
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.