1

Rails 4.2, PostgreSQL 9.3

Model relations are:

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

Situation where I create configurator with product foo and then try to update it to add product foo works fine. I get error has_already_taken.

But when I add two identical products at once validations doesn't work. How do I validate uniqueness of product_id in Nesting model in scope of Configurator?

My views are pretty basic:

= 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

One of the quick solutions is to check uniqueness of product_id's in parameters in controllers action. But I don't like the idea that validation happen in controllers action.

mef_
  • 478
  • 1
  • 12
  • 31

1 Answers1

0

Adding validates_associated on Configurator may help, but I would add a uniqueness constraint to Nesting. In a migration:

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

Also see:

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

Community
  • 1
  • 1
thebenedict
  • 2,539
  • 3
  • 20
  • 29
  • 1
    Also I humanized error message like so in Nesting model. I added `save` method, call `super`, and `rescue ActiveRecord::RecordNotUnique` – mef_ Oct 08 '15 at 07:01