Polymorphic habtm relationships with Rails/ActiveRecord?

Given your explanation of your domain, I've whipped up a small test-driven example of how you might solve your problem. If you see any domain inconsistencies, please feel free to clarify further (I'm using my acts_as_fu gem to whip up test models on the fly) require 'acts_as_fu' # class Task :task_targets, :source => :targetable, :source_type => 'CustomerStore' has_many :software_systems, :through => :task_targets, :source => :targetable, :source_type => 'SoftwareSystem' end # class TaskTarget true belongs_to :task end # class CustomerStore :targetable has_many :tasks, :through => :task_targets end # class SoftwareSystem :targetable has_many :tasks, :through => :task_targets end require 'test/unit' class PolymorphicDomainTest task assert customer_store.tasks. Include?(task) end def test_many_customer_stores_get_task task_a = Task.

Create! Task_b = Task. Create!

Customer_store = CustomerStore. Create! :tasks => task_a, task_b assert customer_store.tasks.

Include?(task_a) assert customer_store.tasks. Include?(task_b) end # Test that software systems can have multiple tasks def test_software_system_gets_task task = Task. Create!

Software_system = SoftwareSystem. Create! Software_system.

Task_targets. Create! :task => task assert software_system.tasks.

Include?(task) end def test_many_software_systems_get_task task_a = Task. Create! Task_b = Task.

Create! Software_system = SoftwareSystem. Create!

:tasks => task_a, task_b assert software_system.tasks. Include?(task_a) assert software_system.tasks. Include?(task_b) end # Test that Tasks can have multiple customer stores def test_task_has_many_customer_stores task = Task.

Create! Customer_store_a = CustomerStore. Create!

Customer_store_b = CustomerStore. Create! Task.

Customer_stores = customer_store_a, customer_store_b task. Save! Task.

Reload assert task. Customer_stores. Include?(customer_store_a) assert task.

Customer_stores. Include?(customer_store_b) end # Test that Tasks can have multiple software systems def test_task_has_many_software_systems task = Task. Create!

Software_system_a = SoftwareSystem. Create! Software_system_b = SoftwareSystem.

Create! Task. Software_systems = software_system_a, software_system_b task.

Save! Task. Reload assert task.

Software_systems. Include?(software_system_a) assert task. Software_systems.

Include?(software_system_b) end end.

Given your explanation of your domain, I've whipped up a small test-driven example of how you might solve your problem. If you see any domain inconsistencies, please feel free to clarify further (I'm using my acts_as_fu gem to whip up test models on the fly). Require 'acts_as_fu' # class Task :task_targets, :source => :targetable, :source_type => 'CustomerStore' has_many :software_systems, :through => :task_targets, :source => :targetable, :source_type => 'SoftwareSystem' end # class TaskTarget true belongs_to :task end # class CustomerStore :targetable has_many :tasks, :through => :task_targets end # class SoftwareSystem :targetable has_many :tasks, :through => :task_targets end require 'test/unit' class PolymorphicDomainTest task assert customer_store.tasks.

Include?(task) end def test_many_customer_stores_get_task task_a = Task. Create! Task_b = Task.

Create! Customer_store = CustomerStore. Create!

:tasks => task_a, task_b assert customer_store.tasks. Include?(task_a) assert customer_store.tasks. Include?(task_b) end # Test that software systems can have multiple tasks def test_software_system_gets_task task = Task.

Create! Software_system = SoftwareSystem. Create!

Software_system. Task_targets. Create!

:task => task assert software_system.tasks. Include?(task) end def test_many_software_systems_get_task task_a = Task. Create!

Task_b = Task. Create! Software_system = SoftwareSystem.

Create! :tasks => task_a, task_b assert software_system.tasks. Include?(task_a) assert software_system.tasks.

Include?(task_b) end # Test that Tasks can have multiple customer stores def test_task_has_many_customer_stores task = Task. Create! Customer_store_a = CustomerStore.

Create! Customer_store_b = CustomerStore. Create!Task.

Customer_stores = customer_store_a, customer_store_b task. Save!Task. Reload assert task.

Customer_stores. Include?(customer_store_a) assert task. Customer_stores.

Include?(customer_store_b) end # Test that Tasks can have multiple software systems def test_task_has_many_software_systems task = Task. Create! Software_system_a = SoftwareSystem.

Create! Software_system_b = SoftwareSystem. Create!Task.

Software_systems = software_system_a, software_system_b task. Save!Task. Reload assert task.

Software_systems. Include?(software_system_a) assert task. Software_systems.

Include?(software_system_b) end end.

This looks pretty good! My only concern is that I'm stuck defining each "targetable" in "Tasks". Is there a way to get around this?

What about Task. Targets/targetables? – Omega Jul 14 '09 at 13:25 I've been gnawing on this for most of today and I'm still not quite satisfied with what I have... It stems from: "has_many :customer_stores, :through => :task_targets, :source => :targetable, :source_type => 'CustomerStore' has_many :software_systems, :through => :task_targets, :source => :targetable, :source_type => 'SoftwareSystem'" Which to me defeats the purpose of polymorphic relationships all together.Is there any way to get it set up so I can get all targetables through Task.

Target AS WELL as being able to to Targetable. Tasks? – Omega Jul 14 '09 at 21:24.

To complement nakajima's answer with regards to your concern, here's how I would do it: class Task Array of targetable_ids targetables = Hash. New { |hash, key| hashkey = } tt. Each do |targetable| targetablestargetable.

Targetable_type Find(targetableskey)}. Flatten end end Make sure to index task_id in table task_targets.

I'm pretty new to Rails, and i'm trying to do a polymorphic HABTM relationship. The problem is that I have three models that I want to relate. The first one is the Event model and then are two kind of attendees: Users and Contacts.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions