Domanda

A hanno due modelli, "Shop" e "Prodotto", collegati tramite Has_Many: attraverso.

Nel modulo del negozio ci sono attributi nidificati per più prodotti e sto avendo un piccolo problema con la convalida delissimo del prodotto.Se inserisco un prodotto, salvalo, prova a inserire lo stesso nome per un nuovo prodotto, i trigger di convalida unicità con successo.

Tuttavia, se inserisco lo stesso nome del prodotto in 2 righe dello stesso modulo nidificato, il modulo è accettato - la convalida delisessità non si attiva.

Suppongo che questo sia un problema abbastanza comune, ma non riesco a trovare alcuna soluzione semplice.Chiunque abbia qualche suggerimento sul modo più semplice per garantire che le convalide di unicità siano rispettate all'interno di la stessa forma nidificata?

Modifica: modello di prodotto incluso sotto

class Product < ActiveRecord::Base

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

  validates_presence_of :name
  validates_uniqueness_of :name
end
.

È stato utile?

Soluzione

È possibile scrivere un validatore personalizzato come

# 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
.

Altri suggerimenti

Per espandere la soluzione di Alberto, il seguente validatore personalizzato accetta un campo (attributo) da convalidare e aggiunge errori alle risorse annidate.

# 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
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top