10

A 有两个模型,“shop”和“product”,通过 has_many :through 链接。

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

但是,如果我在同一个嵌套表单的 2 行中输入相同的产品名称,则该表单被接受 - 不会触发唯一性验证。

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

编辑:产品型号如下

class Product < ActiveRecord::Base

  has_many :shop_products
  has_many :shops, :through => :shop_products

  validates_presence_of :name
  validates_uniqueness_of :name
end
4

3 回答 3

17

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

# 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
于 2012-02-07T20:25:07.430 回答
14

您可以编写一个自定义验证器,例如

# 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
于 2011-03-30T14:19:45.913 回答
0

我在这里找到了答案:

https://rails.lighthouseapp.com/projects/8994/tickets/2160-nested_attributes-validates_uniqueness_of-fails

于 2012-06-12T06:38:32.550 回答