I have a chained polymorphic association on two many-to-many
relationships.
I am using Ruby 1.8.7
I am using Rails 2.3.4
I am using ActiveRecord 2.3.4
I have the following relationship:
GROUP
|
>- GROUPABILITY (polymorphic)
|
TAG
|
>- TAGABILITY (polymorphic)
|
CONTACT
The idea is a CONTACT can have many TAGS and a TAG can belong to
many GROUPS. Because I plan to use both TAGS and GROUPS in more
creative ways is why I want them to be a polymorphic
association.
Models
class Group < ActiveRecord::Base
has_many :groupabilities
has_many :tags, :through => :groupabilities,
:source => :tag,
:conditions => "groupabilities.groupable_type = 'Tag'"
end
class Groupability < ActiveRecord::Base
belongs_to :group
belongs_to :groupable, :polymorphic => true
belongs_to :tag, :class_name => "Tag",
:foreign_key => "groupable_id"
end
class Tag < ActiveRecord::Base
has_many :groupabilities, :as => :groupable
has_many :groups, :through => :groupabilities
has_many :tagabilities
has_many :contacts, :through => :tagabilities,
:source => :contact,
:conditions => "tagabilities.tagable_type = 'Contact'"
end
class Tagability < ActiveRecord::Base
belongs_to :tag
belongs_to :tagable, :polymorphic => true
belongs_to :contact, :class_name => "Contact",
:foreign_key => "tagable_id"
end
class Contact < ActiveRecord::Base
has_many :tagabilities, :as => :tagable
has_many :tags, :through => :tagabilities
end
DB
class CreateGroups < ActiveRecord::Migration
def self.up
create_table :groups do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :groups
end
end
class CreateTags < ActiveRecord::Migration
def self.up
create_table :tags do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :tags
end
end
class CreateContacts < ActiveRecord::Migration
def self.up
create_table :contacts do |t|
t.string :name
t.timestamps
end
end
def self.down
drop_table :contacts
end
end
class CreateTagabilities < ActiveRecord::Migration
def self.up
create_table :tagabilities do |t|
t.integer :tagable_id
t.string :tagable_type
t.integer :tag_id
t.timestamps
end
end
def self.down
drop_table :tagabilities
end
end
class CreateGroupabilities < ActiveRecord::Migration
def self.up
create_table :groupabilities do |t|
t.integer :groupable_id
t.string :groupable_type
t.integer :group_id
t.timestamps
end
end
def self.down
drop_table :groupabilities
end
end
Console
Loading development environment (Rails 2.3.2)
>> c = Contact.create(:name => "First Contact")
=> #<Contact id: 1, name: "First Contact", created_at: "2009-09-25 13:05:06", updated_at: "2009-09-25 13:05:06">
>> t = Tag.create(:name => "First Tag")
=> #<Tag id: 1, name: "First Tag", created_at: "2009-09-25 13:05:31", updated_at: "2009-09-25 13:05:31">
>> g = Group.create(:name => "First Group")
=> #<Group id: 1, name: "First Group", created_at: "2009-09-25 13:05:55", updated_at: "2009-09-25 13:05:55">
>> c.tags
=> []
>> c.tags << t
=> [#<Tag id: 1, name: "First Tag", created_at: "2009-09-25 13:05:31", updated_at: "2009-09-25 13:05:31">]
>> c.tags
=> [#<Tag id: 1, name: "First Tag", created_at: "2009-09-25 13:05:31", updated_at: "2009-09-25 13:05:31">]
>> t.contacts
=> [#<Contact id: 1, name: "First Contact", created_at: "2009-09-25 13:05:06", updated_at: "2009-09-25 13:05:06">]
>> g.tags
=> []
>> t.groups
=> []
>> g.tags << t
=> [#<Tag id: 1, name: "First Tag", created_at: "2009-09-25 13:05:31", updated_at: "2009-09-25 13:05:31">]
>> g.tags
=> [#<Tag id: 1, name: "First Tag", created_at: "2009-09-25 13:05:31", updated_at: "2009-09-25 13:05:31">]
>> t.groups
=> []
>> Groupability.all
=> [#<Groupability id: 1, groupable_id: 1, groupable_type: nil, group_id: 1, created_at: "2009-09-25 13:10:30", updated_at: "2009-09-25 13:10:30">]
Problem
The problem is that PER THE LAST LINE OF CONSOLE, groupable_type
is not being set. It should be set to "Tag". If I manually set the
groupable_type to "Tag" everything works beautifully.
I have tried this in a variety of ways but it seems to be
related to the fact that this is a chained polymorphic
association.