设置和测试以防止ActiveRecord多对多关系中的重复
我有以下关于“项目”和“颜色”之间的多对多关系的课程 和“项目”不应该有重复的“颜色”, 例如:- 如果“项目1”有“蓝色”和“红色”,则我们不能在“项目1”中添加另一个“红色” 这是正确的设置方法吗设置和测试以防止ActiveRecord多对多关系中的重复,activerecord,ruby-on-rails-4,rspec,Activerecord,Ruby On Rails 4,Rspec,我有以下关于“项目”和“颜色”之间的多对多关系的课程 和“项目”不应该有重复的“颜色”, 例如:- 如果“项目1”有“蓝色”和“红色”,则我们不能在“项目1”中添加另一个“红色” 这是正确的设置方法吗 class Item < ActiveRecord::Base has_many :item_colors has_many :colors, :through => item_colors end class Color < ActiveRec
class Item < ActiveRecord::Base
has_many :item_colors
has_many :colors, :through => item_colors
end
class Color < ActiveRecord::Base
has_many :item_colors
has_many :items, :through => item_colors
end
class ItemColor < ActiveRecord::Base
belongs_to :item
belongs_to :color
validates_uniqueness_of :color, scope: :item
end
请告知。当您添加第二种颜色时,这是因为父对象
@项
已保存,即它不是新记录
假设它是一个多:通过关联,它是,这反过来会引发异常,因为您的联接模型ItemColor
无法验证唯一性
在您的情况下,您有两种选择:
救援
异常并手动或手动管理错误消息李>
如果您使用连接模型只是为了添加验证层,那么可以将其删除,改用连接模型并将关联作为一个集合处理,例如
> item = FactoryGirl.create(:item)
> color = FactoryGirl.create(:color)
> 10.times { item.colors |= [color] } # you can add it n times...
> item.colors.count # => 1 ...still only one is saved b/c it is a union set.
你觉得怎么样
更新:如果您确实想显示错误消息,您可以,例如
if item.colors.include?(color)
item.errors.add(:colors, "color already selected")
else
item.colors |= [color]
end
@斯纳克摩尔:这对你有什么帮助吗?很抱歉回复得太晚了。由于开放id问题,我有几天无法登录。我喜欢2选项,但我如何用错误消息提醒用户?我想您不需要错误消息。即使用户多次尝试添加相同的颜色,系统也总是只保存一种,因为它就像一个集合。就用户体验而言,IMHO,错误信息可以被抑制,b/c用户很可能会错误地尝试添加现有颜色。最终,他们的行动将产生预期的结果,不会出现任何错误。然而,如果您真的想警告您的用户,我已经用一个示例解决方案更新了答案。
> item = FactoryGirl.create(:item)
> color = FactoryGirl.create(:color)
> 10.times { item.colors |= [color] } # you can add it n times...
> item.colors.count # => 1 ...still only one is saved b/c it is a union set.
if item.colors.include?(color)
item.errors.add(:colors, "color already selected")
else
item.colors |= [color]
end