Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Serialized Data Validations

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?

like image 352
Randuin Avatar asked Oct 04 '10 16:10

Randuin


2 Answers

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.

like image 89
Larry K Avatar answered Nov 01 '22 11:11

Larry K


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

like image 24
Bryce Avatar answered Nov 01 '22 11:11

Bryce