Para: Parse and Validate Parameters

Strongly-typed languages rely on a few tricks to ensure safety and reliability of its system. With Elixir, one of the most common practices is to enforce types using pattern matchings or guard clauses.

I recently covered a few best practices to consider when using this strategy in my previous article.

However, as our system gets more complex we will often find the task of manually parsing and validating parameters to be somewhat tedious. The sentiment is in fact shared by many, that we can find quite a few libraries that attempt to help solve this problem. Arguably, like many parts of Elixir they were inspired by Rails - case in point: StrongParameters.

What is Para?

Para provides a declarative way to parse and validate parameters. It uses Ecto under the hood, loosely adhering to most of its common public interfaces. The main objective is to simplify the task of building the structure around parsing and validating parameters.

Para can be used within any layers of an Elixir application. Here’s how it might look like for a typical Phoenix application:

Para

The library is available on GitHub and Hex.pm.

So why Para?

Most Elixir developers should be familiar enough with Ecto’s DSL, so using Para should be quite straightforward. What sets it apart are mainly in terms of simpler code structure and useful shortcuts to speed-up development.

Let’s dive a little deeper into some of its features.

1. Contextual

Para allows developers to group a set of actions that belongs to the same context into a single module. For example, when you have a controller named UserController, it would make sense to have a single UserPara module to handle all the validations.

Here’s an example:

defmodule UserPara do
  use Para

  # Validation for :create action
  validator :create do
    required :name
    required :age, :integer
  end

  # Validation for :update action
  validator :update do
    required :name, :string, droppable: true
    required :age, :string, droppable: true
  end
end

2. Powerful and flexible

Para includes an inline validator feature which simplifies the effort to perform additional validation to any specific field. In addition to supporting all of Ecto’s validate_* functions, it can also be used with any custom function.

validator :test do
  required :name, :string, validator: {:validate_length, [max: 128]}
  required :email, :float, validator: {:validate_email, "~r/@/"}
  required :type, :string, validator: :validate_material
end

def validate_material(changeset, params) do
  # ...
end

If that’s not enough, we can also use a custom callback function for each validator to perform any additional data manipulation.

validator :test do
  required :address_line_1
  required :address_line_2
  required :city
  required :zipcode
  required :state
  required :country
  callback :validate_address
end

def validate_address(changeset, params) do
  # ...
end

What’s Next?

Para is still a new library so we need your help to make it better. If you found any issues or would like to suggest a new feature, please feel free to open a new thread on the GitHub repo.