Подтвердить что ты не робот

Rails has_many минимальная проверка обновления размера коллекции

У меня есть ассоциация has_many, которая принимает вложенные атрибуты. Мне нужно, чтобы в коллекции было не менее 1 связанного объекта, поэтому я написал специальный валидатор:

class MinimumCollectionSizeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if value.size < options[:size]
      record.errors[attribute] << (options[:message] || "must have at least #{options[:size]} line.")
    end
  end
end

Модель выглядит так:

has_many :foos, :dependent=>:destroy
accepts_nested_attributes_for :foos
validates :foos, :minimum_collection_size=>{:size=>1}

Это отлично работает с созданием модели, но при обновлении не получается. @my_model.update_attributes(params[:my_model]) возвращает true, даже если все foos удалены _destroy.

Как мне заставить update_attributes вести себя так же, как save?

4b9b3361

Ответ 1

Лучший способ проверки минимального размера коллекции:

validates :my_association, :length => { :minimum => Fixnum}

Ответ 2

SooDesuNe

Да, validates :foos, :length => {:minimum => 1, :message=>"At least one foo" } лучше исходного, но эта же проблема все еще происходит.

Чтобы исправить это, мы можем использовать метод проверки:

validate :validate_foos

private
def validate_foos
  remaining_foos = foos.reject(&:marked_for_destruction?)
  errors.add :foos, "At least one foo" if remaining_foos.empty?

Надеюсь, что это поможет тем, кто столкнулся с одной и той же проблемой.

Ответ 3

Создать валидатор:

class CollectionLengthValidator < ActiveModel::Validations::LengthValidator
  def validate_each(record, attribute, value)
    value = value.respond_to?(:reject) ? value.reject(&:marked_for_destruction?) : value
    super(record, attribute, value)
  end
end

Это проблема с удалением последней записи в коллекции.

Затем используйте в качестве стандартного средства проверки длины:

validates :foos, :collection_length => {:minimum => 1}