Rails validation, knowing which field is invalid?
I had a model that works great.
class Product < ActiveRecord::Base
validates_format_of :field1, with: /\A[0-9\+\-\/\s]+\Z/, allow_nil: true
validates_format_of :field2, with: /\A[0-9\+\-\/\s]+\Z/, allow_nil: true
end
some of my database entries are not valid. these are older records. I want to run a seed that finds these invalid entries
Product.all.each do |product|
next if product.valid?
#
end
I want to clear attributes that are not valid. let me say that product 1 has a value test
in field1
which is invalid. now I want to clear this field and only this.
How do I find invalid fields? something likeproduct.field1.valid?
source to share
The Rails api allows you to get the error message with the method ActiveModel::Errors#get
:
Product.all.each do |product|
product.valid? # => run validation callbacks
product.errors.messages # => {:field1=>["cannot be nil"]}
product.errors.get(:field1) # => ["cannot be nil"]
product.errors.get(:field2) # => nil
# `include?` and `has_key?` works too(it aliases)
product.errors.messages # => {:field1=>["cannot be nil"]}
product.errors.include?(:field1) # => true
product.errors.include?(:field2) # => false
#
end
source to share
It's easy to do, but there are a few things to remember about performance:
- you don't want to just load all your products into memory and iterate over them,
- if possible, you should not try to update them one by one.
This might be an acceptable solution:
invalid_ids = []
Product.find_each(batch_size: 200) do |product|
if !product.valid?
if product.errors.include?(:field_1)
invalid_ids << product.id
end
end
end
Product.where(id: invalid_ids).update_all(field_1: nil)
source to share