问题
I have a field that is serialized to YAML through the default AR behavior. It is currently in an Array of Hashes for examples:
[{'name' => 'hi', 'url' => 'bye'},
{'name' => 'hi', 'url' => 'bye'},
{'name' => 'hi', 'url' => 'bye'}]
Is there a way I can use some basic AR validations on some of these fields?
回答1:
Yes, use the validates_each
method
serialize :urls
validates_each :urls do |record, attr, value|
# value is an array of hashes
# eg [{'name' => 'hi', 'url' => 'bye'}, ...]
problems = ''
if value
value.each{|name_url|
problems << "Name #{name_url['name']} is missing its url. " \
unless name_url['url']}
else
problems = 'Please supply at least one name and url'
end
record.errors.add(:urls, problems) unless problems.empty?
end
Added: You can't use the validations such as validates_length_of
since the validation method doesn't understand the format of your serialized field.
The validates_each
method is good since it enables you to write your own validation method. The method can then add an error to the record if appropriate.
Tip: You can also add an error to the :base
of record.errors rather than to the specific attribute. Sometimes this can help with the formatting of the error messages in your views.
回答2:
Leaving this here in case it helps anyone in the future - I've written a gem to better handle validating serialized attributes. You can just put those validations in a block syntax, the ways you might expect to:
serialize :urls
validates_hash_keys :urls do
validates :name, presence: true
validates :url, presence: true
end
https://github.com/brycesenz/validates_serialized
回答3:
In model
store :field_name, :name
store :field_name, :url
validates :name, presence: true
validates :url, presence: true
It will provide you attribute accessors also so you can use them like normal fields as:
object.name = 'some value' # reader
object.name # writer
object.url = 'some url' # reader
object.url # writer
来源:https://stackoverflow.com/questions/3857220/rails-serialized-data-validations