Repository is archived
No commit activity in last 3 years
No release in over 3 years
Uses the power and familiarity of ActiveModel::Validations to validate hash structures. Designed for detecting and providing feedback on bad requests to your RESTful Web Service.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

~> 4.1.1
 Project Readme

Validates Structure

Validates Structure allows you to easily validate hash-structures using ActiveModel::Validations.

Dependencies

The gem works for ActiveModel 4 and above.

Installation

Simply add the gem to your gemfile:

gem 'validates-structure'

and make sure your activemodel version is at least 4.0.0:

gem 'activemodel', '>=4.0.0'

Remember to

require 'validates-structure'

at the top of the file when defining a new structure.

Canonical Usage Example

require 'validates-structure'

class MyCanonicalValidator < ValidatesStructure::Validator
  key 'foo', Hash do
    key 'bar', Array do
      value Integer, allow_nil: true
    end
    key 'baz', String, format: /\A[0-f]\z/
  end
end

validator = MyCanonicalValidator.new({foo: {bar: [1, 2, nil, 'invalid']}})
validator.valid?
# => false
puts validator.errors.full_messages
# => /foo/bar[3] has class "String" but should be a "Integer"
# => /foo/baz is invalid
# => /foo/baz must not be nil

Quick facts about Validates Structure

  • Validates Structure uses ActiveModel::Validations to validate your hash.
  • Validates Structure automatically validates the type of each declared entry and will also give an error when undeclared keys are present.
  • You can validate that a value are true or false by using the Boolean class (even though there are no Boolean class i Ruby).
  • You can make compound hashes by setting a subclass to ValidatesStructure::Validator as the class in a key or value declaration.
  • It doesn't matter if your structure uses symbols or strings as hash keys.
  • Just like when validating attributes in a model, you can use your own custom validations.

Examples

Minimal example

class MySimpleValidator < ValidatesStructure::Validator
  key 'apa', Integer
end

MySimpleValidator.new(apa: 3).valid?
# => true

Boolean example

class MyBooleanValidator < ValidatesStructure::Validator
  key 'apa', Boolean
end

MyBooleanValidator.new(apa: true).valid?
# => true

Nested example

class MyNestedValidator < ValidatesStructure::Validator
  key 'apa', Hash do
    key 'bepa', String, presence: true
  end
end

validator = MyNestedValidator.new(apa: { bepa: "" })
validator.valid?
# => false
puts validator.errors.full_messages
# => /apa/bepa can't be blank

Array example

class MyArrayValidator < ValidatesStructure::Validator
  key 'apa', Hash do
    key 'bepa', Array do
      value Integer
    end
  end
end

validator = MyArrayValidator.new(apa: { bepa: [1, 2, "3"] })
validator.valid?
# => true
puts validator.errors.full_messages
# => /apa/bepa[2] has class "String" but should be a "Integer"

Compound example

class MyInnerValidator < ValidatesStructure::Validator
  key 'bepa', Integer
end

class MyOuterValidator < ValidatesStructure::Validator
  key 'apa', MyInnerValidator
end

MyOuterValidator.new(apa: { bepa: 3 }).valid?
# => true

Custom validator example

class OddValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors.add attribute, "can't be even." if value.even?
  end
end

class MyCustomValidator < ValidatesStructure::Validator
  key 'apa', Integer, odd: true
end

MyCustomValidator.new(apa: 3).valid?
# => true

Documentation

This documentation is about the modules, classes, methods and options of ValidatesStructure. For documentation on ActiveModel::Validations see the ActiveModel documentation.

ValidatesStructure::Validator

self.key(index, klass, validations={}, &block)

Sets up a requirement on the form 'index' => klass that are validated with validations and containing children on the form specified in &block.

Parameters

index - The string or symbol by which to retrieve the value

klass - The required class of the value. If klass is a subclass of ValidatesStructure::Validator then the value is validated as specified in its definition.

validations - A hash with ActiveModel:Validations on the same format as for the validates method.

&block - A block of nested key and/or value declarations. Only applicable if klass is an Array or Hashe.

self.value(klass, validations={},&block)

Sets up a requirement like self.key but without an index. Useful for structures that are accessed by a numeric index such as Arrays.

Parameters

klass - The required class of the value. If klass is a subclass of ValidatesStructure::Validator then the value is validated as specified in its definition.

validations - A hash with ActiveModel:Validations on the same format as for the validates method.

&block - A block of nested key and/or value declarations. Only applicable if klass is an Array or Hashe.

Some History

This project was initiated by the good fellows at PugglePay who felt there should be some easy, familiar way of validating their incoming json requests and wanted to share their solution with the world.

Contributing

  1. Fork the project
  2. Create a feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push branch to remote (git push origin my-new-feature)
  5. Make a Pull Request