# Polymorphic joins work one way, but not the other

**URL:** <https://www.ruby-forum.com/t/polymorphic-joins-work-one-way-but-not-the-other/53842>\
**Category:** Rails\
**Created:** [February 15, 2006, 4:42am UTC](https://www.ruby-forum.com/t/polymorphic-joins-work-one-way-but-not-the-other/53842 "2006-02-15T04:42:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![rubyruy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/4491bb/32.png) [@rubyruy](https://www.ruby-forum.com/u/rubyruy)\
**Post date:** [February 15, 2006, 4:42am UTC](https://www.ruby-forum.com/t/polymorphic-joins-work-one-way-but-not-the-other/53842/1 "2006-02-15T04:42:32Z")

</div>

I’ve been using polymorphic joins from edge rails based on about 5 lines  
of advice Rick O. gave me over IRC. There’s some sparse documentation  
popping up but it seems to cover a somewhat different case.

Anyway - I pretty much got it to work - save for one detail. Here’s what  
I have:

class Event \< ActiveRecord::Base  
belongs\_to :attachable, :polymorphic =\> true  
#events table has attachable\_type and attachable\_id fields  
end

class Task \< ActiveRecord::Base  
has\_many :events, :as =\> :attachable  
#tasks tables is nothing special  
end

and now a unit test:

#there’s some fixtures above  
def test\_polymorphics  
assert tasks(:simple\_task).events \<\< events(:simple\_event\_1)  
assert tasks(:simple\_task).events \<\< events(:simple\_event\_2)  
assert events(:simple\_event\_1).save!  
assert tasks(:simple\_task).save!  
assert\_equal 2, tasks(:simple\_task).events.size  
assert\_equal “simple event 1”,  
tasks(:simple\_task).events.find(1).note  
assert\_equal “simple task”, events(:simple\_event\_1).task.title  
end

All asserts pass except the last one:

ruby test/unit/task\_test.rb  
Loaded suite test/unit/task\_test  
Started  
E.  
Finished in 1.103896 seconds.

1. Error:  
test\_polymorphics(TaskTest):  
NoMethodError: undefined method `task' for #<Event:0x22258a0> _RAILS_ROOT_/config/../vendor/rails/activerecord/lib/active_record/base.rb:1565:in`method\_missing’  
test/unit/task\_test.rb:17:in `test\_polymorphics’

2 tests, 7 assertions, 0 failures, 1 errors

(path replaced with RAILS\_ROOT since I’m secretive like that)

In other words - I can do stuff like @task.events \<\< @event but NOT  
@event.task = @task ! (or indeed @event.task.\* ) @tasks.events \<\<  
definitely works - I even checked the db and the attachment\_type/id  
fields are set exactly as expected.

It kind of makes sense - since I never actually mention :tasks anywhere  
in Event’s model definition. But how exactly do I mention it?

I looked over the example in the wiki but it doesn’t seem to touch on  
this problem at all (and it kind of tries to do something different too)

- SO - any help is apretiated.

It could also be that this particular piece of functionality simply  
hasn’t been implemented yet…

---

<div class="post-metadata">

**Author:** ![rubyruy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/4491bb/32.png) [@rubyruy](https://www.ruby-forum.com/u/rubyruy)\
**Post date:** [February 15, 2006, 6:17am UTC](https://www.ruby-forum.com/t/polymorphic-joins-work-one-way-but-not-the-other/53842/2 "2006-02-15T06:17:55Z")

</div>

> In other words - I can do stuff like @task.events \<\< @event but NOT  
> @event.task = @task ! (or indeed @event.task.\* ) @tasks.events \<\<  
> definitely works - I even checked the db and the attachment\_type/id  
> fields are set exactly as expected.

Try this:

class Event \< ActiveRecord::Base  
belongs\_to :attachable, :polymorphic =\> true

def task=(task)  
self.attachable = task  
end  
end

If you have a lot of properties, you can earn points towards your  
metaprogramming merit badge:

class Event \< ActiveRecord::Base  
belongs\_to :attachable, :polymorphic =\> true

%w(task project stuff).each do |model|  
define\_method(“#{model}=”) do |value|  
self.attachable = value  
end  
end  
end

–  
Rick O.  
[http://techno-weenie.net](http://techno-weenie.net)

---

<div class="post-metadata">

**Author:** ![rubyruy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/4491bb/32.png) [@rubyruy](https://www.ruby-forum.com/u/rubyruy)\
**Post date:** [February 15, 2006, 7:57am UTC](https://www.ruby-forum.com/t/polymorphic-joins-work-one-way-but-not-the-other/53842/3 "2006-02-15T07:57:25Z")

</div>

Oh my! So it isn’t implemented!

Are there plans to do so later?

The way you mention only adds the = method right? It won’t add all of  
task’s methods proper from what I can tell.

It would be nice to rework the syntax for the new polymorphic stuff a  
little. It’s a complicated concept, sure, but it’s really a lot less  
approachable then the rest of AR-magic.

Here’s what I’d like.  
class Comment \< AR:B  
belongs\_to :page, :or =\> :file, :or =\> :thing. :or =\> :other\_thing,  
:as =\> :attachable  
end

It isn’t quite as elegant (since there would have to be an ‘implied’ :or  
=\> before :page and :as is actually changing behavior from has\_many) but  
it would be far more easy to understand imho.

Rick O. wrote:

> > In other words - I can do stuff like @task.events \<\< @event but NOT  
> > @event.task = @task ! (or indeed @event.task.\* ) @tasks.events \<\<  
> > definitely works - I even checked the db and the attachment\_type/id  
> > fields are set exactly as expected.
> 
> Try this:
> 
> class Event \< ActiveRecord::Base  
> belongs\_to :attachable, :polymorphic =\> true
> 
> def task=(task)  
> self.attachable = task  
> end  
> end
> 
> If you have a lot of properties, you can earn points towards your  
> metaprogramming merit badge:
> 
> class Event \< ActiveRecord::Base  
> belongs\_to :attachable, :polymorphic =\> true
> 
> %w(task project stuff).each do |model|  
> define\_method(“#{model}=”) do |value|  
> self.attachable = value  
> end  
> end  
> end
> 
> –  
> Rick O.  
> [http://techno-weenie.net](http://techno-weenie.net)
