# How to model a polymorphic relationship?

**URL:** <https://www.ruby-forum.com/t/how-to-model-a-polymorphic-relationship/148161>\
**Category:** Rails\
**Created:** [September 9, 2008, 11:15pm UTC](https://www.ruby-forum.com/t/how-to-model-a-polymorphic-relationship/148161 "2008-09-09T23:15:00Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![rpitting](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rpitting](https://www.ruby-forum.com/u/rpitting)\
**Post date:** [September 9, 2008, 11:15pm UTC](https://www.ruby-forum.com/t/how-to-model-a-polymorphic-relationship/148161/1 "2008-09-09T23:15:00Z")

</div>

I have read many articles about polymorphic associations in Rails and  
also about plugins for this purpose (mainly the has\_many\_polymorphs  
plugin).

Unfortunately, I am still unsure how to solve my problem:

Let’s say you have these models you want to set in relation to each  
other: Person, Document, Realty.

You want to link polymorphic objects with each other. Let’s call the  
“join-class” Relationship. A Relationship has a name and at least two  
link-partners.

A Relationship between Person and Document could be called “Creator”.

A Relationship between a Person and a Realty would have the name  
“Owner”.

A Relationship between a Document and a Realty would have the name  
“Lease”.

So, how to implement this idea, and to be able to easly extend the list  
of linkable objects? Is it possible to avoid any association-definitions  
in the linkable models?

Thank you for your help,

Reiner

---

<div class="post-metadata">

**Author:** ![rpitting](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rpitting](https://www.ruby-forum.com/u/rpitting)\
**Post date:** [September 9, 2008, 11:25pm UTC](https://www.ruby-forum.com/t/how-to-model-a-polymorphic-relationship/148161/2 "2008-09-09T23:25:22Z")

</div>

Reiner,

I don’t believe you have the need for polymorphic associations in the  
above example as you have a seperate association “type” already specced  
out for each relation

class Person \< ActiveRecord::Base  
has\_many :documents  
has\_many :realties  
end

class Document \< ActiveRecord::Base  
belongs\_to :owner, class\_name =\> “Person”  
belongs\_to :realty  
end

class Realty \< ActiveRecord::Base  
belongs\_to :owner, class\_name =\> “Person”  
has\_many :leases, class\_name =\> “Document”  
end

Where do you need polymorphic associations in the above example?

p.s. I know next to nothing about real estate so please forgive me if I  
got your relation wrong between documents and realties… does a realty  
have many leases or is it the other way around?? 🙂

hth  
ilan

> So, how to implement this idea, and to be able to easly extend the list  
> of linkable objects? Is it possible to avoid any association-definitions  
> in the linkable models?
> 
> Thank you for your help,
> 
> Reiner

---

<div class="post-metadata">

**Author:** ![rpitting](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rpitting](https://www.ruby-forum.com/u/rpitting)\
**Post date:** [September 9, 2008, 11:43pm UTC](https://www.ruby-forum.com/t/how-to-model-a-polymorphic-relationship/148161/3 "2008-09-09T23:43:51Z")

</div>

Hi Ilan,

thank you for your answer:

Ilan B. wrote:

> class Person \< ActiveRecord::Base  
> has\_many :documents  
> has\_many :realties  
> end
> 
> class Document \< ActiveRecord::Base  
> belongs\_to :owner, class\_name =\> “Person”  
> belongs\_to :realty  
> end
> 
> class Realty \< ActiveRecord::Base  
> belongs\_to :owner, class\_name =\> “Person”  
> has\_many :leases, class\_name =\> “Document”  
> end

Well, this is exacly what I want to avoid. As the project grows, more  
and more classes can be linked to each other. With your approach, each  
class would start with a listing of “hard-wired” associations.

Imagine 10 classes being able to be linked to each other - what a mess  
to maintain in each class!

Instead, I would like something like this:

class Relationship \< ActiveRecord::Base  
has\_one :the\_one # can be any model  
has\_one :the\_other # can be any model  
end

or, even more flexible

class Relationship \< ActiveRecord::Base  
has\_many :members # a list model of any type  
end

But how to do this with “the magic” of Rails?

---

<div class="post-metadata">

**Author:** ![rpitting](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rpitting](https://www.ruby-forum.com/u/rpitting)\
**Post date:** [September 10, 2008, 3:01pm UTC](https://www.ruby-forum.com/t/how-to-model-a-polymorphic-relationship/148161/4 "2008-09-10T15:01:57Z")

</div>

Reiner,

My suggestion then is to come up with your classes first and then make a  
design. A very common pitfall is to design for something that “may”  
happen and then later face over engineered code… In the late nineties,  
we called this the YAGNI principle which stood for “You Aint Going to  
Need It!”

If you propose your new more complete class model, I can help with your  
polymorphic associations (If you still need them)…

Lastly, remember that PAs are not free, they add extra conditions to the  
select clauses which can be quite costly with improper or imcomplete  
indexing.

Reiner Pittinger wrote:

> But how to do this with “the magic” of Rails?

---

<div class="post-metadata">

**Author:** ![rpitting](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rpitting](https://www.ruby-forum.com/u/rpitting)\
**Post date:** [September 10, 2008, 9:51pm UTC](https://www.ruby-forum.com/t/how-to-model-a-polymorphic-relationship/148161/5 "2008-09-10T21:51:17Z")

</div>

Search for “Rails double polymorphic” in Google…

[http://wiki.rubyonrails.org/rails/pages/ManytoManyPolymorphicAssociations](http://wiki.rubyonrails.org/rails/pages/ManytoManyPolymorphicAssociations)  
[http://blog.evanweaver.com/files/doc/fauna/has\_many\_polymorphs/files/README.html](http://blog.evanweaver.com/files/doc/fauna/has_many_polymorphs/files/README.html)

or just assume that everyone else will do the googling for you…

---

<div class="post-metadata">

**Author:** ![rpitting](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rpitting](https://www.ruby-forum.com/u/rpitting)\
**Post date:** [September 10, 2008, 8:38pm UTC](https://www.ruby-forum.com/t/how-to-model-a-polymorphic-relationship/148161/6 "2008-09-10T20:38:54Z")

</div>

Dear Ilan,

although I just supplied just three basic models, my application already  
contains more than 15 different models that should be linked to each  
other.

Some more examples:

- I need a relationship between two documents ("Like: Document B is an  
attachment to Document A).
- I need a relationship beween a Key-Class (the ones you use to open a  
house 😉 and a RealtyItem (name: “Key House-Entrance”).
- I need a relationship between two Persons, to model something like  
“Assistent”

I could supply a dozen more. This is why already now I want a flexible  
modelling of these relationships.

I image a table to store the relationships like this:

id name the\_one\_id the\_one\_class the\_other\_id the\_other\_class  
1 Owner 2 Person 3 RealtyItem  
2 Assistant 5 Person 5 Person  
3 Lease#333 5 Document 3 RealtyItem

It seems so simple - but how do I achieve it correctly using Rails?

---

<div class="post-metadata">

**Author:** ![rpitting](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/71c47a/32.png) [@rpitting](https://www.ruby-forum.com/u/rpitting)\
**Post date:** [September 18, 2008, 11:06pm UTC](https://www.ruby-forum.com/t/how-to-model-a-polymorphic-relationship/148161/7 "2008-09-18T23:06:45Z")

</div>

I came to the solution using the has\_many\_polymorphs plugins:

The correct modelling is:

class Relationship \< ActiveRecord::Base

belongs\_to :relationship\_owner, :polymorphic =\> true  
belongs\_to :relationship\_partner, :polymorphic =\> true

acts\_as\_double\_polymorphic\_join(  
:relationship\_owners =\>[:people, :realties, :documents],  
:relationship\_partners =\> [:people, :realties, :documents]  
)

end

… and the migration:

class CreateRelationships \< ActiveRecord::Migration  
def self.up  
create\_table :relationships do |t|  
t.string :name

```
  t.references :relationship_owner, :polymorphic => true
  t.references :relationship_partner, :polymorphic => true

  t.timestamps
end

```

end

def self.down  
drop\_table :relationships  
end  
end
