I have a has_many
association that accepts nested attributes. I need for there to be a minimum of 1 associated object in the collection, so I wrote a custom validator:
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
The model looks like:
has_many :foos, :dependent=>:destroy
accepts_nested_attributes_for :foos
validates :foos, :minimum_collection_size=>{:size=>1}
This works great on model creation, but fails miserable on update. @my_model.update_attributes(params[:my_model])
returns true even if all the foos are removed by _destroy.
How do I get update_attributes
to behave the same as save
?
A better way to validate the minimum size of a collection:
validates :my_association, :length => { :minimum => Fixnum}
SooDesuNe
Yes, validates :foos, :length => {:minimum => 1, :message=>"At least one foo" }
is better than the original one, but the same issue still happens.
To fix it, we could use validate method:
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?
Hope it helps to who encountered the same problem.
Create validator:
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
This is resolve problem with delete last record in collection.
Then use in model as standard length validator:
validates :foos, :collection_length => {:minimum => 1}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With