与Rails / ActiveRecord的多形态habtm关系 [英] Polymorphic habtm relationships with Rails/ActiveRecord
问题描述
如何创建与Rails / ActiveRecord的多态性has_and_belongs_to_many关系?
我看到的大多数示例涉及到创建一个belongs_to关系,限制了我的多边形仅与一个父母相关:
表:任务
表:Tasks_Targets
表:CustomerStore
表:SoftwareSystem
CustomerStore和SoftwareSystem都将在这种情况下是可定向类型。根据我的理解,如果我按照大多数例子来实现多态关系,我只能将Targetable与一次相关联。
谢谢!
div class =h2_lin>解决方案鉴于您对域名的解释,我已经提出了一个小的测试驱动的例子,说明如何解决您的问题。如果您看到任何域名不一致,请随时进一步澄清(我正在使用我的 acts_as_fu gem
在飞行中鞭打测试模型)。
require'acts_as_fu'
#class Task< ActiveRecord :: Base
build_model(:tasks)do
integer:task_target_id
has_many:task_targets
has_many:customer_stores,,through => :task_targets,:source => :targetable,:source_type => 'CustomerStore'
has_many:software_systems,:through => :task_targets,:source => :targetable,:source_type => 'SoftwareSystem'
end
#class TaskTarget< ActiveRecord :: Base
build_model(:task_targets)do
string:targetable_type
integer:targetable_id
integer:task_id
belongs_to:targetable,:polymorphic = > true
belongs_to:task
end
#class CustomerStore< ActiveRecord :: Base
build_model(:customer_stores)do
has_many:task_targets,:as => :targetable
has_many:tasks,:through => :task_targets
end
#class SoftwareSystem< ActiveRecord :: Base
build_model(:software_systems)do
has_many:task_targets,:as => :targetable
has_many:tasks,:through => :task_targets
end
require'test / unit'
class PolymorphicDomainTest< Test :: Unit :: TestCase
#测试客户商店可以有多个任务
def test_customer_store_gets_task
task = Task.create!
customer_store = CustomerStore.create!
customer_store.task_targets.create! :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
#测试该软件系统可以有多个任务
def test_software_system_gets_task
task = Task.create!
software_system = SoftwareSystem.create!
software_system.task_targets.create! :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
#测试任务可以有多个客户商店
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
#测试该任务可以有多个软件系统
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
How would I go about creating a polymorphic has_and_belongs_to_many relationship with Rails/ActiveRecord?
Most of the examples I see involve creating a belongs_to relationship which limits my polymorphic-side to being related to only one parent:
Table: Task
Table: Tasks_Targets
Table: CustomerStore
Table: SoftwareSystem
Both CustomerStore and SoftwareSystem would be of type "Targetable" in this circumstance. From what I understand, if I implement the polymorphic relationship as most examples show, I'd only be able to relate a Targetable to a Task once.
Some clarification might help as most searches online still leave some of the theory behind this relationship unexplained...
Thanks!
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 < ActiveRecord::Base
build_model(:tasks) do
integer :task_target_id
has_many :task_targets
has_many :customer_stores, :through => :task_targets, :source => :targetable, :source_type => 'CustomerStore'
has_many :software_systems, :through => :task_targets, :source => :targetable, :source_type => 'SoftwareSystem'
end
# class TaskTarget < ActiveRecord::Base
build_model(:task_targets) do
string :targetable_type
integer :targetable_id
integer :task_id
belongs_to :targetable, :polymorphic => true
belongs_to :task
end
# class CustomerStore < ActiveRecord::Base
build_model(:customer_stores) do
has_many :task_targets, :as => :targetable
has_many :tasks, :through => :task_targets
end
# class SoftwareSystem < ActiveRecord::Base
build_model(:software_systems) do
has_many :task_targets, :as => :targetable
has_many :tasks, :through => :task_targets
end
require 'test/unit'
class PolymorphicDomainTest < Test::Unit::TestCase
# Test that customer stores can have multiple tasks
def test_customer_store_gets_task
task = Task.create!
customer_store = CustomerStore.create!
customer_store.task_targets.create! :task => 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
这篇关于与Rails / ActiveRecord的多形态habtm关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!