Contracts

Requests are designed by contract in order to enforce correctness and type-safe definitions

HTTP Requests

Every HTTP request message has a specific form:

POST /path HTTP/1.1
Host: example.com

foo=bar&baz=bat

An HTTP message is either a request from a client to a server or a response from a server to a client.

Azu Contract Request

Requests are designed by contract in order to enforce correctness. What this means is that requests are strictly typed and can have preconditions. With this concept.

The Request provides concise, type-safe, and self-validated request objects.

struct UserContract
  include Azu::Contract
  
  getter name : String
  validate name, message: "Param name must be present.", presence: true
end

Benefits:

  • Self-documented request objects.

  • Type-safe requests and parameters

  • Enables Focused and effective testing.

  • JSON body requests render object instances.

Azu::Contract are provided by tight integration with the Schema shard

Example Use:

Request Instances

Requests can be initialized are initialized in the background and property is available to the Endpoint of the same name of the request as the camel case.

Requests can be initialized from JSON, YAML, and the standard initializes method new.

UserContract.from_json(pyaload: String)
UserContract.new(params: Hash(String, String))

Instance Methods

Instance Method

Description

validate

A macro to define validation rules for your request

valid?

Validates the request object and returns true or false

validate!

Validates and raises an exception when invalid

rules

returns a list of rules to be applied on validation

params

Request params. See Params

to_json

A JSON representation of the request

to_yaml

A YAML representation of the request

Custom Validators

When the built-in validation helpers are not enough for your needs, you can write your own validators or validation methods as you prefer.

Defining Custom Validators

Custom validators are simple classes that inherit from Schema::Validator. These classes must implement the valid? method which takes a record as an argument and performs the validation on it. The custom validator is called using the valid? or validate! method.

class ConfirmPasswordValidator < Schema::Validator
  getter :record, :field, :message

  def initialize(@record : Authority::NewOwnerRequest)
    @field = :password
    @message = "Password did not match with confirm password."
  end

  def valid? : Array(Schema::Error)
    if @record.password != @record.confirm_password
      [Schema::Error.new @field, @message]
    else
      [] of Schema::Error
    end
  end
end

Using Custom Validators

To enable the custom validator to your structs or classes by simply defining the use ConfirmPasswordValidator

module Authority
  struct NewOwnerRequest
    include Request

    getter first_name : String = ""
    getter last_name : String = ""
    getter email : String = ""
    getter username : String = ""
    getter password : String = ""
    getter confirm_password : String = ""
    
    ## Use Custom Validator
    use ConfirmPasswordValidator

    validate first_name, message: "Param first_name must be present.", presence: true
    validate last_name, message: "Param last_name must be present.", presence: true
    validate email, message: "Param email must be present.", presence: true
    validate username, message: "Param username must be present.", presence: true
    validate password, message: "Param password must be present.", presence: true
  end
end

Last updated