polymprphic == confusion

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

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

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

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

google for acts_as_double_polymorphic_join

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.

I guess you are using the has_many_polymorphs plugin. http://github.com/fauna/has_many_polymorphs/tree/master

looks interesting. i'll give it a try.

thanks, scott

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

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