Вложенные атрибуты Rails: требуется как минимум две записи - PullRequest
10 голосов
/ 30 ноября 2010

Как сделать так, чтобы для отправки продукта требовалось как минимум две записи опций?

class Product < ActiveRecord::Base
  belongs_to :user
  has_many :options, :dependent => :destroy
  accepts_nested_attributes_for :options, :allow_destroy => :true, :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
  validates_presence_of :user_id, :created_at
  validates :description, :presence => true, :length => {:minimum => 0, :maximum => 500}
end

class Option < ActiveRecord::Base
  belongs_to :product
  validates :name, :length => {:minimum => 0, :maximum => 60}                  
end

Ответы [ 4 ]

17 голосов
/ 30 ноября 2010
class Product < ActiveRecord::Base
  #... all your other stuff
  validate :require_two_options

  private
    def require_two_options
      errors.add(:base, "You must provide at least two options") if options.size < 2
    end
end
12 голосов
/ 22 ноября 2012

Просто соображение по поводу ответа karmajunkie: я бы использовал size вместо count, потому что, если в каком-то встроенном (и не сохраненном) вложенном объекте есть ошибки, он не будет рассматриваться (его еще нет в базе данных).

class Product < ActiveRecord::Base
  #... all your other stuff
  validate :require_two_options

  private
    def require_two_options
      errors.add(:base, "You must provide at least two options") if options.size < 2
    end
end
2 голосов
/ 02 января 2014

Если ваша форма позволяет удалять записи, то .size не будет работать, поскольку она включает записи, помеченные для уничтожения.

Мое решение было:

validate :require_two_options

private
 def require_two_options
    i = 0
    product_options.each do |option|
      i += 1 unless option.marked_for_destruction?
    end
    errors.add(:base, "You must provide at least two option") if i < 2
 end
0 голосов
/ 31 октября 2016

Код Tidier, протестирован с Rails 5:

class Product < ActiveRecord::Base
  OPTIONS_SIZE_MIN = 2
  validate :require_two_options

  private

  def options_count_valid?
    options.reject(&:marked_for_destruction?).size >= OPTIONS_SIZE_MIN
  end

  def require_two_options
    errors.add(:base, 'You must provide at least two options') unless options_count_valid?
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...