class Cat < ActiveRecord::Base
has_many :catbowls
has_many :bowls, through: :catbowls
end
class CatBowl < ActiveRecord::Base
belongs_to :cats
belongs_to :bowls
end
class Bowl < ActiveRecord::Base
has_many :catbowls
has_many :cats, through: :catbowls
end
在导轨控制台中,我可以给猫一个碗:
cat = Cat.create(name: 'tibbles')
bowl = Bowl.create(color: 'blue')
cat.catbowls #=> []
cat.catbowls.create(bowl_id: bowl.id)
cat.catbowls #=> [#<Bowl id: 1, color: "blue", created_at: "2014-04-23 22:53:15", updated_at: "2014-04-23 22:53:15">]
这是有道理的,并且存在以下关联:
CatBowl.all #=> [#<Bowl id: 1, cat_id: 1, bowl_id: 1>]
然而,这是我的问题。如果我再次创建关联,它实际上并没有改变结果,但我确实得到了一个无效的相同catbowl关系。
cat.catbowls.create(bowl_id: bowl.id)
cat.catbowls #=> [#<Bowl id: 1, color: "blue", created_at: "2014-04-23 22:53:15", updated_at: "2014-04-23 22:53:15">]>
这种关系与前一种关系相同,完全没用:
CatBowl.all #=> [#<Bowl id: 1, cat_id: 1, bowl_id: 1>,#<Bowl id: 2, cat_id: 1, bowl_id: 1>]
那么如何阻止现有关系的创建?应该使用什么方法链来替换 cat.catbowls.create ,并创建一个关系,除非已经存在?
我可以使用unless语句来执行此操作,
cat.catbowls.create(bowl_id: bowl.id) unless Catbowl.where(cat_id: cat.id, bowl_id:bowl.id).present?
然而,这非常麻烦并导致大量查询。我想要做的是如此常见,我想知道一些铁魔法是否可以帮助我?
答案 0 :(得分:1)
首先将's'移除到猫和碗上 class CatBowl&lt;的ActiveRecord :: Base的 belongs_to:cat belongs_to:碗 端
然后创建桥接条目
cat.bowls&lt;&lt;碗强>
但它无法阻止重复。 防止重复处理条件
条件可能会喜欢: (cat.bowls.find_by(id: bowl.id) || cat.bowls << bowl) if rails 4
(cat.bowls.find_by_id(bowl.id)|| cat.bowls&lt;&lt; bowl)if rails 3
答案 1 :(得分:0)
似乎find_or_create_by
就是答案:
Catbowl.find_or_create_by(cat_id: cat.id, bowl_id: bowl.id )
通过方法cat_id
和bowl_id
传递方法,我们会检查仅涉及这些列的唯一性,并忽略所有其他列(例如id
)。
答案 2 :(得分:0)
cat = Cat.create(name: 'tibbles')
bowl = Bowl.create(color: 'blue')
简单地将碗与猫联系起来:
cat.bowls << bowl
将碗与猫联系起来,但先检查是否存在关系:
cat.bowls << bowl unless cat.bowl_ids.include?(bowl.id)