Validates Serialized
ActiveModel provides ways to validate attributes, and to serialize objects. This gem provides some ActiveModel extensions and syntactic sugar to simplify the process of validating those serialized objects.
This gem provides:
- A generic validation method that supports any serializable object
- A validation method for serialized hashes, to validate specific key values
- A validation method for serialized hashes, to support validating all hash values
- A validation method for serialized arrays, to support validating all array values
Installation
Add this line to your application's Gemfile:
gem 'validates_serialized', '~> 0.0.1'
And then execute:
$ bundle
Or install it yourself as:
$ gem install validates_serialized
Validating a generic object
Here we have an example, serializable class called 'Person' with a name and age attribute.
class Person
def initialize(h={})
h.each {|k,v| send("#{k}=",v)}
end
def name
@name ||= nil
end
def name=(val)
@name = val
end
def age
@age ||= nil
end
def age=(val)
@age = val
end
end
Now we can serialize this object and validate its properties in another class
class Family < ActiveRecord::Base
include ActiveModel
...
serialize :father, Person
validates_serialized :father do
validates :name, presence: true
validates :age, numericality: { greater_than: 21 }
end
end
The validations will be run against the serialized object whenever validation hooks are fired. E.g.
# With valid serialized object
valid_father = Person.new(name: "Bob", age: 31)
family = Family.new(father: valid_father)
family.valid? #=> true
# With invalid serialized object
valid_father = Person.new(name: "Bob", age: 13)
family = Family.new(father: valid_father)
family.valid? #=> false
family.errors[:father] #=> ["age must be greater than 13"]
Validating a serialized hash by keys
class Comment < ActiveRecord::Base
include ActiveModel
...
serialize :metadata, Hash
validates_hash_keys :metadata do
validates :timestamp, presence: true
validates :locale, presence: true
end
end
# With valid hash
comment = Comment.new(metadata: { timestamp: Time.new(2014, 1, 1), locale: "Ohio" })
comment.valid? #=> true
# With invalid hash
comment = Comment.new(metadata: { timestamp: Time.new(2014, 1, 1), locale: nil })
comment.valid? #=> false
comment.errors[:metadata] #=> ["locale can't be blank"]
Validating serialized hash values
class Comment < ActiveRecord::Base
include ActiveModel
...
serialize :ratings, Hash
validates_hash_values :ratings, numericality: { greater_than: 0 }
end
# With valid hash
comment = Comment.new(ratings: { tom: 4, jim: 2 })
comment.valid? #=> true
# With invalid hash
comment = Comment.new(ratings: { tom: 4, jim: -1 })
comment.valid? #=> false
comment.errors[:ratings] #=> ["ratings must be greater than 0"]
Validating a serialized array (syntax #1)
class Comment < ActiveRecord::Base
include ActiveModel
...
serialize :tags, Array
validates_array_values_with :tags, length: { minimum: 4 }
end
# With valid hash
comment = Comment.new(tags: ["ruby" "rails"])
comment.valid? #=> true
# With invalid hash
comment = Comment.new(tags: ["ruby" "rails", "ror"])
comment.valid? #=> false
comment.errors[:tags] #=> ["tags is too short (minimum is 4 characters)"]
Validating a serialized array (syntax #2)
class Comment < ActiveRecord::Base
include ActiveModel
...
serialize :tags, Array
validates_each_in_array :tags do
validates :value, length: { minimum: 4 } #the attribute 'value' with access each value
end
end
# With valid hash
comment = Comment.new(tags: ["ruby" "rails"])
comment.valid? #=> true
# With invalid hash
comment = Comment.new(tags: ["ruby" "rails", "ror"])
comment.valid? #=> false
comment.errors[:tags] #=> ["tags is too short (minimum is 4 characters)"]
Customizing error message for Array validation
There is activerecord.errors.messages.array_has_invalid_value
translation key available for Array validation errors.
The two options are available in translation: attribute
and text
Default error message is: "#{attribute} has a value that #{text}"
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request