Media-Types Validation (Ruby)
The repository for the media_types
gem currently lives at GitHub: sleeplessbyte/media-types-ruby
.
MediaTypes
Media Types based on scheme, with versioning, views, suffixes and validations.
This library makes it easy to define schemas that can be used to validate JSON objects based on their Content-Type.
Installation
Add this line to your application’s Gemfile:
gem 'media_types'
And then execute:
$ bundle
Or install it yourself as:
$ gem install media_types
Usage
Define a validation:
require 'media_types'
module Acme
MediaTypes::set_organisation Acme, 'acme'
class FooValidator
include MediaTypes::Dsl
use_name 'foo'
validations do
attribute :foo, String
end
end
end
Validate an object:
Acme::FooValidator.validate!({ foo: 'bar' })
Full example
require 'media_types'
class Venue
include MediaTypes::Dsl
def self.organisation
'mydomain'
end
use_name 'venue'
validations do
version 2 do
attribute :name, String
collection :location do
attribute :latitude, Numeric
attribute :longitude, Numeric
attribute :altitude, AllowNil(Numeric)
end
link :self
link :route, allow_nil: true
end
version 1 do
attribute :name, String
attribute :coords, String
attribute :updated_at, String
link :self
end
view 'create' do
collection :location do
attribute :latitude, Numeric
attribute :longitude, Numeric
attribute :altitude, AllowNil(Numeric)
end
version 1 do
collection :location do
attribute :latitude, Numeric
attribute :longitude, Numeric
attribute :altitude, AllowNil(Numeric)
end
end
end
end
end
Schema Definitions
If you include ‘MediaTypes::Dsl’ in your class you can use the following functions within a validation do
block to define your schema:
attribute
Adds an attribute to the schema, if a +block+ is given, uses that to test against instead of +type+
param | type | description |
---|---|---|
key | Symbol
|
the attribute name |
opts | Hash
|
options to pass to Scheme or Attribute
|
type | Class , === , Scheme
|
The type of the value, can be anything that responds to === , or scheme to use if no &block is given. Defaults to Object without a &block and to Hash with a &block .
|
optional: | TrueClass , FalseClass
|
if true, key may be absent, defaults to false
|
&block | Block
|
defines the scheme of the value of this attribute |
Add an attribute named foo, expecting a string
require 'media_types'
class MyMedia
include MediaTypes::Dsl
validations do
attribute :foo, String
end
end
MyMedia.valid?({ foo: 'my-string' })
# => true
Add an attribute named foo, expecting nested scheme
class MyMedia
include MediaTypes::Dsl
validations do
attribute :foo do
attribute :bar, String
end
end
end
MyMedia.valid?({ foo: { bar: 'my-string' }})
# => true
any
Allow for any key. The &block
defines the Schema for each value.
param | type | description |
---|---|---|
scheme | Scheme , NilClass
|
scheme to use if no &block is given
|
allow_empty: | TrueClass , FalsClass
|
if true, empty (no key/value present) is allowed |
expected_type: | Class ,
|
forces the validated value to have this type, defaults to Hash . Use Object if either Hash or Array is fine
|
&block | Block
|
defines the scheme of the value of this attribute |
Add a collection named foo, expecting any key with a defined value
class MyMedia
include MediaTypes::Dsl
validations do
collection :foo do
any do
attribute :bar, String
end
end
end
end
MyMedia.valid?({ foo: [{ anything: { bar: 'my-string' }, other_thing: { bar: 'other-string' } }] })
# => true
not_strict
Allow for extra keys in the schema/collection even when passing strict: true
to #validate!
Allow for extra keys in collection
class MyMedia
include MediaTypes::Dsl
validations do
collection :foo do
attribute :required, String
not_strict
end
end
end
MyMedia.valid?({ foo: [{ required: 'test', bar: 42 }] })
# => true
collection
Expect a collection such as an array or hash. The &block
defines the Schema for each item in that collection.
param | type | description |
---|---|---|
key | Symbol
|
key of the collection (same as #attribute )
|
scheme | Scheme , NilClass , Class
|
scheme to use if no &block is given or Class of each item in the
|
allow_empty: | TrueClass , FalseClass
|
if true, empty (no key/value present) is allowed |
expected_type: | Class ,
|
forces the validated value to have this type, defaults to Array . Use Object if either Array or Hash is fine.
|
optional: | TrueClass , FalseClass
|
if true, key may be absent, defaults to false
|
&block | Block
|
defines the scheme of the value of this attribute |
Collection with an array of string
class MyMedia
include MediaTypes::Dsl
validations do
collection :foo, String
end
end
MyMedia.valid?({ collection: ['foo', 'bar'] })
# => true
Collection with defined scheme
class MyMedia
include MediaTypes::Dsl
validations do
collection :foo do
attribute :required, String
attribute :number, Numeric
end
end
end
MyMedia.valid?({ foo: [{ required: 'test', number: 42 }, { required: 'other', number: 0 }] })
# => true
link
Expect a link with a required href: String
attribute
param | type | description |
---|---|---|
key | Symbol
|
key of the link (same as #attribute )
|
allow_nil: | TrueClass , FalseClass
|
if true, value may be nil |
optional: | TrueClass , FalseClass
|
if true, key may be absent, defaults to false
|
&block | Block
|
defines the scheme of the value of this attribute, in addition to the href attribute
|
Links as defined in HAL, JSON-Links and other specs
class MyMedia
include MediaTypes::Dsl
validations do
link :_self
link :image
end
end
MyMedia.valid?({ _links: { self: { href: 'https://example.org/s' }, image: { href: 'https://image.org/i' }} })
# => true
Link with extra attributes
class MyMedia
include MediaTypes::Dsl
validations do
link :image do
attribute :templated, TrueClass
end
end
end
MyMedia.valid?({ _links: { image: { href: 'https://image.org/{md5}', templated: true }} })
# => true
Validation
If your type has a validations, you can now use this media type for validation:
Venue.valid?({
#...
})
# => true if valid, false otherwise
Venue.validate!({
# /*...*/
})
# => raises if it's not valid
If an array is passed, check the scheme for each value, unless the scheme is defined as expecting a hash:
expected_hash = Scheme.new(expected_type: Hash) { attribute(:foo) } expected_object = Scheme.new { attribute(:foo) }
expected_hash.valid?({ foo: ‘string’ }) # => true
expected_hash.valid?([{ foo: ‘string’ }]) # => false
expected_object.valid?({ foo: ‘string’ }) # => true
expected_object.valid?([{ foo: ‘string’ }]
API
A defined schema has the following functions available:
valid?
Example: Venue.valid?({ foo: 'bar' })
Allows passing in validation options as a second parameter.
validate!
Example: Venue.validate!({ foo: 'bar' })
Allows passing in validation options as a second parameter.
validatable?
Example: Venue.version(42).validatable?
Tests wether the current configuration of the schema has a validation defined.
register
Example: Venue.register
Registers the media type to the registry.
view
Example: Venue.view('create')
Returns a schema validator configured with the specified view.
version
Example: Venue.version(42)
Returns a schema validator configured with the specified version.
suffix
Example: Venue.suffix(:json)
Returns a schema validator configured with the specified suffix.
identifier
Example: Venue.version(2).identifier
(returns 'application/vnd.application.venue.v2'
)
Returns the IANA compatible Media Type Identifier for the configured schema.
available_validations
Example: Venue.available_validations
Returns a list of all the schemas that are defined.
Related
MediaTypes::Serialization
: :cyclone: Add media types supported serialization to Rails.
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake test
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, call bundle exec rake release
to create a new git tag, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at SleeplessByte/media-types-ruby