Skip to content

joaquimadraz/compel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

204 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Compel

Code Climate Test Coverage

Ruby Object Coercion and Validation

This is a straight forward way to validate any Ruby object: just give an object and the schema.

The motivation was to create an integration for RestMyCase to have validations before any business logic execution and to build a easy way coerce and validate params on Sinatra.

The schema builder is based on Joi.

Usage

object = {
  first_name: 'Joaquim',
  birth_date: '1989-0',
  address: {
    line_one: 'Lisboa',
    post_code: '1100',
    country_code: 'PT'
  }
}

schema = Compel.hash.keys({
  first_name: Compel.string.required,
  last_name: Compel.string.required,
  birth_date: Compel.datetime,
  address: Compel.hash.keys({
    line_one: Compel.string.required,
    line_two: Compel.string.default('-'),
    post_code: Compel.string.format(/^\d{4}-\d{3}$/).required,
    country_code: Compel.string.in(['PT', 'GB']).default('PT')
  })
})

Compel.run(object, schema) # or schema.validate(object)

Will return a Compel::Result object:

=> <Compel::Result
  @errors={
    "last_name" => ["is required"],
    "birth_date" => ["'1989-0' is not a parsable datetime with format: %FT%T"],
    "address" => {
      "post_code" => ["must match format ^\\d{4}-\\d{3}$"]
    }
  },
  @valid=false,
  @value={
    "first_name" => "Joaquim",
    "birth_date" => "1989-0",
    "address" => {
      "line_one" => "Lisboa",
      "post_code" => "1100",
      "country_code" => "PT",
      "line_two" => "-"
    },
    "errors" => {
      "last_name" => ["is required"],
      "birth_date" => ["'1989-0' is not a parsable datetime with format: %FT%T"],
      "address" => {
        "post_code" => ["must match format ^\\d{4}-\\d{3}$"]
      }
    }
  }>

There are 4 ways to run validations:

Method Behaviour
#run Validates and returns a Compel::Result (see below)
#run! Validates and raises Compel::InvalidObjectError exception with the coerced params and errors.
#run? Validates and returns true or false.
schema#validate Check below

==========================

Schema Builder API

Compel#any

Any referes to any type that is available to coerce with Compel. Methods length, min_length and max_length turn the object to validate into a string to compare the length.

Methods:

  • is(``value``)
  • required
  • default(``value``)
  • length(``integer``)
  • min_length(``integer``)
  • max_length(``integer``)
  • if
    • if(->(value){ value == 1 })
    • if{|value| value == 1 }
    • if{:custom_validation} # Check the specs for now, I'm rewriting the docs ;)

==========================

Compel#array

Methods:

  • #items(``schema``)

Examples:

. [1, 2, 3]
. [{ a: 1, b: 2}
. { a: 3, b: 4 }]

==========================

Compel#hash

Methods:

  • keys(``schema_hash``)

Examples:

. { a: 1,  b: 2, c: 3 }

==========================

Compel#date

Methods:

  • format(``ruby_date_format``)
  • iso8601, set format to: %Y-%m-%d

==========================

Compel#datetime & Compel#time

Methods:

  • format(``ruby_date_format``)
  • iso8601, set format to: %FT%T

==========================

Compel#json

Examples:

. "{\"a\":1,\"b\":2,\"c\":3}"

==========================

Compel#boolean

Examples:

. 1/0
. true/false
. 't'/'f'
. 'yes'/'no'
. 'y'/'n'

==========================

Compel#string

Methods:

  • in(``array``)
  • min(``value``)
  • max(``value``)
  • format(``regexp``)
  • email
  • url

==========================

Compel#integer

Methods:

  • in(``array``)
  • min(``value``)
  • max(``value``)

==========================

Compel#float

Methods:

  • in(``array``)
  • min(``value``)
  • max(``value``)

==========================

Schema Validate

For straight forward validations, you can call #validate on schema and it will return a Compel::Result object.

result = Compel.string
               .format(/^\d{4}-\d{3}$/)
               .required
               .validate('1234')

puts result.errors
# => ["must match format ^\\d{4}-\\d{3}$"]

Compel Result

Simple object that encapsulates a validation result.

Method Behaviour
#value the coerced value or the input value is invalid
#errors array of errors is any.
#valid? true or false
#raise? raises a Compel::InvalidObjectError if invalid, otherwise returns #value

Custom Options

Custom error message

Examples:

schema = Compel.string.required(message: 'this is really required')

result = schema.validate(nil)

p result.errors
=> ["this is really required"]

schema = Compel.string.is('Hello', message: 'give me an Hello!')

result = schema.validate(nil)

p result.errors
=> ["give me an Hello!"]

==========================

Sinatra Integration

If you want to use with Sinatra, here's an example:

class App < Sinatra::Base

  set :show_exceptions, false
  set :raise_errors, true

  before do
    content_type :json
  end

  helpers do

    def compel(schema)
      params.merge! Compel.run!(params, Compel.hash.keys(schema))
    end

  end

  error Compel::InvalidObjectError do |exception|
    status 400
    { errors: exception.object[:errors] }.to_json
  end

  configure :development do
    set :show_exceptions, false
    set :raise_errors, true
  end

  post '/api/posts' do
    compel({
      post: Compel.hash.keys({
        title: Compel.string.required,
        body: Compel.string,
        published: Compel.boolean.default(false)
      }).required
    })

    params.to_json
  end

end

###Installation

Add this line to your application's Gemfile:

gem 'compel', '~> 0.5.0'

And then execute:

$ bundle

Get in touch

If you have any questions, write an issue or get in touch @joaquimadraz

About

Ruby Object Coercion and Validation

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages