Comparing polymorphic property to same object fails

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

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

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.