Rails 3:嵌套fields_for的唯一性validation

A有两个型号,“商店”和“产品”,通过has_many:through链接。

在商店表单中有多个产品的嵌套属性,我在产品的唯一性validation方面遇到了一些麻烦。 如果我输入产品,保存它,然后尝试为新产品输入相同的名称,则唯一性validation会成功触发。

但是,如果我在同一嵌套表单的两行中输入相同的产品名称,则表单被接受 – 唯一性validation不会触发。

我猜这是一个相当普遍的问题,但我找不到任何简单的解决方案。 任何人都有最简单的方法建议,以确保在同一嵌套表格中遵守唯一性validation?

编辑:产品型号包括在下面

class Product  :shop_products validates_presence_of :name validates_uniqueness_of :name end 

你可以编写一个自定义validation器

 # app/validators/products_name_uniqueness_validator.rb class ProductsNameUniquenessValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) record.errors[attribute] << "Products names must be unique" unless value.map(&:name).uniq.size == value.size end end # app/models/shop.rb class Shop < ActiveRecord::Base validates :products, :products_name_uniqueness => true end 

为了扩展Alberto的解决方案,以下自定义validation器接受要validation的字段(属性),并将错误添加到嵌套资源。

 # config/initializers/nested_attributes_uniqueness_validator.rb class NestedAttributesUniquenessValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) unless value.map(&options[:field]).uniq.size == value.size record.errors[attribute] << "must be unique" duplicates = value - Hash[value.map{|obj| [obj[options[:field]], obj]}].values duplicates.each { |obj| obj.errors[options[:field]] << "has already been taken" } end end end # app/models/shop.rb class Shop < ActiveRecord::Base validates :products, :nested_attributes_uniqueness => {:field => :name} end