验证范围内嵌套关联的唯一性

Validate uniqueness of nested association in scope

Rails4.2,PostgreSQL 9.3

模型关系是:

class Nesting < ActiveRecord::Base
  belongs_to :product
  belongs_to :configurator, touch: true

  validates :product_id, uniqueness: { scope: :configurator }
end

class Configurator < ActiveRecord::Base
  has_many   :nestings, dependent: :destroy
  has_many   :products, through: :nestings

  accepts_nested_attributes_for :nestings, reject_if: :all_blank, allow_destroy: true
end

我使用产品 foo 创建配置器然后尝试更新它以添加产品 foo 的情况工作正常。我收到错误 has_already_taken.

但是当我同时添加两个相同的产品时,验证不起作用。如何在 Configurator 范围内验证 Nesting 模型中 product_id 的唯一性?

我的观点很基础:

= simple_form_for @configurator, remote: true do |f|
  = f.simple_fields_for :nestings do |nesting|
    = render 'nesting_fields', f: nesting
  = link_to_add_association 'add product', f, :nestings, class: 'btn btn-default'
  = f.button :submit

_nesting_fields.html.slim

.nested-fields
  .form-inline
    = f.association :product, collection: @products
    = link_to_remove_association f, class: 'btn btn-default' do
      .glyphicon.glyphicon-remove

快速解决方案之一是检查控制器操作中参数 product_id's 的唯一性。但我不喜欢在控制器操作中进行验证的想法。

Configurator 上添加 validates_associated 可能会有所帮助,但我会向 Nesting 添加唯一性约束。在迁移中:

class AddUniqueIndexToNesting < ActiveRecord::Migration
  def change
    add_index :nestings, [:configurator_id, :product_id], unique: true
  end
end

另见:

Rails 3: Uniqueness validation for nested fields_for

Rails - Validate Nested Attributes Uniqueness with scope parent of parent

https://github.com/rails/rails/issues/1572