# Polymprphic == confusion

**URL:** <https://www.ruby-forum.com/t/polymprphic-confusion/157180>\
**Category:** Rails\
**Created:** [January 8, 2009, 7:36am UTC](https://www.ruby-forum.com/t/polymprphic-confusion/157180 "2009-01-08T07:36:39Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![scottnj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9e5f3/32.png) [@scottnj](https://www.ruby-forum.com/u/scottnj)\
**Post date:** [January 8, 2009, 7:36am UTC](https://www.ruby-forum.com/t/polymprphic-confusion/157180/1 "2009-01-08T07:36:39Z")

</div>

I have been having trouble setting up some relations.

I want to be able to do this:

user.contact\_items # an array of addresses, websites, phone  
numbers, etc.  
user.addresses # an array of addresses  
user.websites # an array of websites  
user.phone\_numbers # an array of phone numbers  
etc.

and the same for businesses, charities, etc.

Since users, businesses, and charities all can have multiple contact  
items I assume a polymorphic relation makes sense.

I also want to be able to do  
address.owner # a user, business, or charity  
website.owner # a user, business, or charity  
phone\_number.owner # a user, business, or charity  
etc.

After much searching, reading and experimenting, my head is beginning  
to hurt. Can someone get me pointed in the right direction? How do I  
setup my models? Will it be possible to add fields to my join table so  
I can flag contact items with things like verified, public, labels,  
etc?

## OWNERS

class Users  
has\_many ???  
belongs\_to ???

class Businesses  
has\_many ???  
belongs\_to ???

class Charities  
has\_many ???  
belongs\_to ???

## JOIN TABLE

class ContactItems  
has\_many ???  
belongs\_to ???  
#public:boolean  
#verified:boolean  
#label:string

## CONTACT ITEMS

class Addresses  
has\_many ???  
belongs\_to ???

class EmailAddresses  
has\_many ???  
belongs\_to ???

class PhoneNumbers  
has\_many ???  
belongs\_to ???

class Websites  
has\_many ???  
belongs\_to ???

---

<div class="post-metadata">

**Author:** ![scottnj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9e5f3/32.png) [@scottnj](https://www.ruby-forum.com/u/scottnj)\
**Post date:** [January 8, 2009, 9:59am UTC](https://www.ruby-forum.com/t/polymprphic-confusion/157180/2 "2009-01-08T09:59:45Z")

</div>

Maybe the below will help. I also know that railsenvy has a good video  
on this.

First of all, it is the tables and associations that are plural, not  
the classes.  
I suggest that you would use single table inheritance for the users  
business etc.  
You need to have a type column defined in the owners table to signify  
class for the record

Here’s my suggestion:

class Owner \< ActiveRecord::Base  
has\_many :addresses, :through =\> :contact\_items  
has\_many :websites, :through =\> :contact\_items  
has\_many :phone\_numbers, :through =\> :contact\_items  
end  
class User \< Owner  
end  
class Business \< Owner  
end  
class Charities \< Owner  
end

# migration

create\_table :owners do |t|  
…  
t.string :type  
end

Polymorphic Association could be is solved like this

class ContactItem \< ActiveRecord::Base  
belongs\_to :owners  
belongs\_to :contacts, :polymorphic =\> true  
end

# migration

create\_table :contact\_item do |t|  
…  
t.string :contact\_type  
t.integer :contact\_id  
end

class Address \< ActiveRecord::Base  
has\_one :owner, :thorugh =\> :contact\_items  
end

class EmailAddress \< ActiveRecord::Base  
has\_one :owner, :thorugh =\> :contact\_items  
end  
class PhoneNumber \< ActiveRecord::Base  
has\_one :owner, :thorugh =\> :contact\_items  
end  
class Website \< ActiveRecord::Base  
has\_one :owner, :thorugh =\> :contact\_items  
end

You can use either belongs\_to or has\_one on the above classes

---

<div class="post-metadata">

**Author:** ![scottnj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9e5f3/32.png) [@scottnj](https://www.ruby-forum.com/u/scottnj)\
**Post date:** [January 8, 2009, 10:00am UTC](https://www.ruby-forum.com/t/polymprphic-confusion/157180/3 "2009-01-08T10:00:56Z")

</div>

End the link to railsenvy video tutorial:  
[http://www.railsenvy.com/2007/8/8/activerecord-tutorial](http://www.railsenvy.com/2007/8/8/activerecord-tutorial)

---

<div class="post-metadata">

**Author:** ![scottnj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9e5f3/32.png) [@scottnj](https://www.ruby-forum.com/u/scottnj)\
**Post date:** [January 8, 2009, 6:22pm UTC](https://www.ruby-forum.com/t/polymprphic-confusion/157180/4 "2009-01-08T18:22:29Z")

</div>

google for acts\_as\_double\_polymorphic\_join

From my app,

Table name: linkages

id :integer(11) not null, primary key  
origin\_id :integer(11)  
origin\_type :string(20)  
destin\_id :integer(11)  
destin\_type :string(20)

In linkage.rb:

belongs\_to :origin, :polymorphic =\> true  
belongs\_to :destin, :polymorphic =\> true

acts\_as\_double\_polymorphic\_join(  
:origins =\> [list your models that can be origins],  
:destins =\> [list your models that can be destins]  
)

Pretty sweet plugin.

---

<div class="post-metadata">

**Author:** ![scottnj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9e5f3/32.png) [@scottnj](https://www.ruby-forum.com/u/scottnj)\
**Post date:** [January 8, 2009, 6:10pm UTC](https://www.ruby-forum.com/t/polymprphic-confusion/157180/5 "2009-01-08T18:10:24Z")

</div>

It looks like that is an option that might work, but is there a way to  
do this without using single table inheritance?

Is it possible to do something like this in rails?

## Owners

class User \< ActiveRecord::Base  
has\_many :contact\_items, :through =\> :contact\_links  
has\_many :addresses, :through? =\> :contact\_links?, :as?  
=\> :contact\_items?  
has\_many :…  
end  
class Business \< ActiveRecord::Base  
has\_many :contact\_items, :through =\> :contact\_links  
has\_many :…  
end  
class Charity \< ActiveRecord::Base  
has\_many :contact\_items, :through =\> :contact\_links  
has\_many :…  
end

## Double Polymorphic Join Model???

class ContactLink \< ActiveRecord::Base  
# id:int  
# owner\_id:int  
# owner\_type:string  
# contact\_item\_id:int  
# contact\_item\_type:string

```
  belongs_to :owners, :polymorphic => true
  belongs_to :contact_items, :polymorphic => true

```

end

## Contact Items

class Address \< ActiveRecord::Base  
has\_one :owner, :through =\> :contact\_links  
end  
class EmailAddress \< ActiveRecord::Base  
has\_one :owner, :through =\> :contact\_links  
end  
class PhoneNumber \< ActiveRecord::Base  
has\_one :owner, :through =\> :contact\_links  
end

---

<div class="post-metadata">

**Author:** ![scottnj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9e5f3/32.png) [@scottnj](https://www.ruby-forum.com/u/scottnj)\
**Post date:** [January 8, 2009, 8:28pm UTC](https://www.ruby-forum.com/t/polymprphic-confusion/157180/6 "2009-01-08T20:28:39Z")

</div>

I guess you are using the has\_many\_polymorphs plugin.  
[http://github.com/fauna/has\_many\_polymorphs/tree/master](http://github.com/fauna/has_many_polymorphs/tree/master)

looks interesting. i’ll give it a try.

thanks,  
scott

---

<div class="post-metadata">

**Author:** ![scottnj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9e5f3/32.png) [@scottnj](https://www.ruby-forum.com/u/scottnj)\
**Post date:** [January 8, 2009, 11:26pm UTC](https://www.ruby-forum.com/t/polymprphic-confusion/157180/7 "2009-01-08T23:26:14Z")

</div>

I couldn’t find a complete example of a double polymorphic  
relationship so I will post what I have in case someone comes across  
this using Google. It seems to be working so far, but I don’t know if  
I have everything setup correctly yet.

# install as a plugin or as a gem

git submodule add git://github.com/fauna/has\_many\_polymorphs.git  
vendor/plugins/has\_many\_polymorphs  
git submodule init  
git submodule update

# setup the models

ruby script/generate model User name:string  
ruby script/generate model Business name:string  
ruby script/generate model Charity name:string

ruby script/generate model Address street:string street2:string  
city:string state:string zip:string  
ruby script/generate model EmailAddress address:string  
ruby script/generate model Website address:string  
ruby script/generate model PhoneNumber number:string

ruby script/generate model Linkage

# edit the linkage migration

class CreateLinkages \< ActiveRecord::Migration  
def self.up  
create\_table :linkages do |t|  
t.references :origin, :polymorphic =\> true  
t.references :destin, :polymorphic =\> true  
t.timestamps  
end  
end  
def self.down  
drop\_table :linkages  
end  
end

# add the relationships to the models

## Origins

class User \< ActiveRecord::Base  
has\_many\_polymorphs :destins, :from =\>  
[:addresses, :email\_addresses, :phone\_numbers, :websites], :through  
=\> :linkages  
end  
class Business \< ActiveRecord::Base  
has\_many\_polymorphs :destins, :from =\>  
[:addresses, :email\_addresses, :phone\_numbers, :websites], :through  
=\> :linkages  
end  
class Charity \< ActiveRecord::Base  
has\_many\_polymorphs :destins, :from =\>  
[:addresses, :email\_addresses, :phone\_numbers, :websites], :through  
=\> :linkages  
end

## Double Polymorphic Join Model

class Linkage \< ActiveRecord::Base  
# id:int  
# origin\_id:int  
# origin\_type:string  
# destin\_id:int  
# destin\_type:string

```
  belongs_to :origin, :polymorphic => true
  belongs_to :destin, :polymorphic => true

  acts_as_double_polymorphic_join(
        :origins => [:users, :businesses, :charities],
        :destins =>

```

[:addresses, :email\_addresses, :phone\_numbers, :websites]  
)  
end

## Destins

class Address \< ActiveRecord::Base  
has\_many\_polymorphs :origins, :from =\>  
[:users, :businesses, :charities], :through =\> :linkages  
end  
class EmailAddress \< ActiveRecord::Base  
has\_many\_polymorphs :origins, :from =\>  
[:users, :businesses, :charities], :through =\> :linkages  
end  
class PhoneNumber \< ActiveRecord::Base  
has\_many\_polymorphs :origins, :from =\>  
[:users, :businesses, :charities], :through =\> :linkages  
end

## How It Works

rake db:migrate  
ruby script/console

> > u=User.new  
> > u.name=“Scott”  
> > u.save  
> > w=Website.new  
> > w.address=“[http://google.com](http://google.com)”  
> > w.save  
> > u.destins \<\< w  
> > u.destins  
> > =\> [#\<Website id: 1, address: “[http://google.com](http://google.com)”, created\_at:  
> > “2009-01-08 21:55:12”, updated\_at: “2009-01-08 21:55:12”\>]  
> > w.origins  
> > =\> [#\<User id: 1, name: “scott”, created\_at: “2009-01-08 21:54:00”,  
> > updated\_at: “2009-01-08 21:54:00”\>]  
> > u.websites  
> > =\> [#\<Website id: 1, address: “[http://google.com](http://google.com)”, created\_at:  
> > “2009-01-08 21:55:12”, updated\_at: “2009-01-08 21:55:12”\>]

---

<div class="post-metadata">

**Author:** ![scottnj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b9e5f3/32.png) [@scottnj](https://www.ruby-forum.com/u/scottnj)\
**Post date:** [January 9, 2009, 12:08am UTC](https://www.ruby-forum.com/t/polymprphic-confusion/157180/8 "2009-01-09T00:08:26Z")

</div>

On Jan 8, 5:25 pm, scott [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I couldn’t find a complete example of a double polymorphic  
> relationship so I will post what I have in case someone comes across  
> this using Google. It seems to be working so far, but I don’t know if  
> I have everything setup correctly yet.

My last post was wrong. The only place we need to define the  
relationships is in the join model, the other models can be blank. It  
is even cleaner now!!!  
One problem I still have is the “destins” (addresses ,phones ,emails,  
etc.) can belong to many “origins”. I need to make this work as a  
has\_one instead of a has\_many.

git submodule add git://github.com/fauna/has\_many\_polymorphs.git  
vendor/plugins/has\_many\_polymorphs  
git submodule init  
git submodule update

ruby script/generate model User name:string  
ruby script/generate model Business name:string  
ruby script/generate model Charity name:string

ruby script/generate model Address street:string street2:string  
city:string state:string zip:string  
ruby script/generate model EmailAddress address:string  
ruby script/generate model Website address:string  
ruby script/generate model PhoneNumber number:string

ruby script/generate model Linkage

class CreateLinkages \< ActiveRecord::Migration  
def self.up  
create\_table :linkages do |t|  
t.references :origin, :polymorphic =\> true  
t.references :destin, :polymorphic =\> true  
t.timestamps  
end  
end  
def self.down  
drop\_table :linkages  
end  
end

## Origins

class User \< ActiveRecord::Base  
end  
class Business \< ActiveRecord::Base  
end  
class Charity \< ActiveRecord::Base  
end

## Double Polymorphic Join Model

class Linkage \< ActiveRecord::Base  
# id:int  
# origin\_id:int  
# origin\_type:string  
# destin\_id:int  
# destin\_type:string

```
  belongs_to :origin, :polymorphic => true
  belongs_to :destin, :polymorphic => true

  acts_as_double_polymorphic_join(
        :origins => [:users, :businesses, :charities],
        :destins =>

```

[:addresses, :email\_addresses, :phone\_numbers, :websites]  
)  
end

## Destins

class Address \< ActiveRecord::Base  
end  
class EmailAddress \< ActiveRecord::Base  
end  
class PhoneNumber \< ActiveRecord::Base  
end

## How It Works

ruby script/console

> > u=User.new  
> > u.name=“Scott”  
> > u.save  
> > w=Website.new  
> > w.address=“[http://google.com](http://google.com)”  
> > w.save  
> > u.destins \<\< w  
> > u.destins  
> > =\> [#\<Website id: 1, address: “[http://google.com](http://google.com)”, created\_at:  
> > “2009-01-08 21:55:12”, updated\_at: “2009-01-08 21:55:12”\>]  
> > w.origins  
> > =\> [#\<User id: 1, name: “scott”, created\_at: “2009-01-08 21:54:00”,  
> > updated\_at: “2009-01-08 21:54:00”\>]  
> > u.websites  
> > =\> [#\<Website id: 1, address: “[http://google.com](http://google.com)”, created\_at:  
> > “2009-01-08 21:55:12”, updated\_at: “2009-01-08 21:55:12”\>]
