我试图弄清楚如何使用ActiveRecord关系来关联可以在一行中包含另一个模型的多个实例的模型。例如,在一个模型中使用has_many:dogs,在另一个模型中使用belongs_to:dog表示在一个模型中,“dog_id”将引用一个实例:dog。但是,我希望能够在我的相关(has_many)模型中有多个:dog实例,例如dog_id1,dog_id2,dog_id3等。请参阅下面的代码以了解我的意思。我怎么能这样做?
我有以下型号:
--tp.rb
class Tp < ActiveRecord::Base
has_many :dogs
has_many :cats
has_many :stars
attr_accessible :dog_id1, :dog_id2, :dog_id3, :dog_id4, :cat_id1, :cat_id2, :cat_id3, :cat_id4, :star_id, :tp_id
end
--dog.rb
class Dog < ActiveRecord::
belongs_to :tp
attr_accessible :dog_id, :dog_name
end
--cat.rb
class Cat < ActiveRecord::Base
belongs_to :tp
attr_accessible :cat_id, :cat_name
end
--star.rb
class Star < ActiveRecord::Base
belongs_to :tp
attr_accessible :patient_id
end
答案 0 :(得分:1)
我认为你的belongs_to
/ has_many
有点倒退了。
对于您的示例,
class Tp < ActiveRecord::Base
has_many :dogs
has_many :cats
has_many :stars
end
Tp
在其数据库行中没有任何dog_id
,cat_id
或star_id
。在其他模型中设置belongs_to
时,
class Dog < ActiveRecord::Base
belongs_to :tp
end
class Cat < ActiveRecord::Base
belongs_to :tp
end
class Star < ActiveRecord::Base
belongs_to :tp
end
您应该为每个模型(tp_id
表,dogs
表和cats
表添加stars
。
然后,拨打
tp = Tp.find(123)
查找Tp
id
等于123
SELECT * FROM tps WHERE id = 123;
并致电
cats = tp.cats
dogs = tp.dogs
stars = tp.stars
查找所有Cat
,Dog
和Star
个实例tp_id
等于123
SELECT * FROM cats WHERE tp_id = 123;
SELECT * FROM dogs WHERE tp_id = 123;
SELECT * FROM stars WHERE tp_id = 123;
如果您需要Cat
个实例属于许多Tp
个实例,而Tp
个实例需要有许多Cat
个实例,那么您应该查看Rails的{{3 }或has_and_belongs_to_many。
has_and_belongs_to
关系需要新表cats_tps
,dogs_tps
和stars_tps
。这些表的架构为
cats_tps
cat_id
tp_id
dogs_tps
dog_id
tp_id
stars_tps
star_id
tp_id
然后在你的模特中
class Tp < ActiveRecord::Base
has_and_belongs_to_many :dogs
has_and_belongs_to_many :cats
has_and_belongs_to_many :stars
end
class Dog < ActiveRecord::Base
has_and_belongs_to_many :tps
end
class Cat < ActiveRecord::Base
has_and_belongs_to_many :tps
end
class Star < ActiveRecord::Base
has_and_belongs_to_many :tps
end
现在,正在运行
tp = Tp.find(123)
cats = tp.cats
生成SQL
SELECT "cats".* FROM "cats" INNER JOIN "cats_tps" ON "cats"."id" = "cats_tps"."cat_id" WHERE "cats_tps"."tp_id" = 123;
这是查询的必要条件(给我一个属于Tp 123的所有cat_ids的列表)然后(给我所有匹配这些猫ID的猫)。
生成cats_tps
联接表可以通过像
class CreateCatsTps < ActiveRecord::Migration
def change
create_table :cats_tps, :id => false do |t|
t.belongs_to :cat
t.belongs_to :tp
end
end
end
这适用于简单连接,但您可能希望使用has_many :through
。这是因为cats_tps
表格中没有关于此Cat
何时或为何属于Tp
或此Tp
属于Cat
的信息。同样,如果您添加Bird
,Horse
,Frog
和Snake
模型,则必须创建birds_tps
,horses_tps
,{{ 1}}和frogs_tps
表。呸。
要创建snakes_tps
关系,您需要创建一个在语义上有意义的新模型,该模型将has_many :through
链接到Tp
。例如,让我们说Cat
走猫。您可以创建一个Tp
模型,将Walk
与Cat
相关联。
Tp
现在,该关系类似于class Walk < ActiveRecord::Base
belongs_to :cat
belongs_to :tp
attr_accessible :price, :duration, :interval # these attributes describe the Walk relationship
end
class Cat < ActiveRecord::Base
has_many :walks
has_many :tps, :through => :walks
end
class Tp < ActiveRecord::Base
has_many :walks
has_many :cats, :through => :walks
end
,但您可以包含有关步行关系的元数据。另外,假设has_and_belongs_to_many
还会遛狗。您可以将Tp
转换为多态belongs_to :cat
关系,以便belongs_to :animal
可以走猫,狗,老鼠,兔子,马......你的名字。
Tp
此关系是使用
等迁移创建的class Walk < ActiveRecord::Base
belongs_to :animal, :polymorphic => true
belongs_to :tp
attr_accessible :price, :duration, :interval # these attributes describe the Walk relationship
end
class Cat < ActiveRecord::Base
has_many :walks, :as => :animal
has_many :tps, :through => :walks
end
class Dog < ActiveRecord::Base
has_many :walks, :as => :animal
has_many :tps, :through => :walks
end
class Tp < ActiveRecord::Base
has_many :walks
has_many :cats, :through => :walks, :source => :animal, :source_type => 'Cat'
has_many :dogs, :through => :walks, :source => :animal, :source_type => 'Dog'
end
答案 1 :(得分:0)
这是错误的
attr_accessible :dog_id1, :dog_id2, :dog_id3, :dog_id4, :cat_id1, :cat_id2, :cat_id3, :cat_id4, :star_id, :tp_id
您的狗模型有一个tp_id
,has_many
和belongs_to
允许您tp_instance.dogs
获取一系列匹配的{{1}狗模型}
答案 2 :(得分:0)
从TP模型中移除:dog_id(s)
并将:tp_id
放入您的狗模型中。这将允许您从TP到Dog有一对多的关系