View Source Parameter.Schema (Parameter v0.8.1)

The first step for building a schema for your data is to create a schema definition to model the external data. This can be achieved by using the Parameter.Schema macro.

schema

Schema

The example below mimics an User model that have one main_address and a list of phones.

defmodule User do
  use Parameter.Schema

  param do
    field :first_name, :string, key: "firstName", required: true
    field :last_name, :string, key: "lastName", required: true, default: ""
    has_one :main_address, Address, key: "mainAddress", required: true
    has_many :phones, Phone
  end
end

defmodule Address do
  use Parameter.Schema

  param do
    field :city, :string, required: true
    field :street, :string
    field :number, :integer
  end
end

defmodule Phone do
  use Parameter.Schema

  param do
    field :country, :string
    field :number, :integer
  end
end

Parameter offers other ways for creating a schema such as nesting the has_one and has_many fields. This require module name as the second parameter using do at the end:

defmodule User do
  use Parameter.Schema

  param do
    field :first_name, :string, key: "firstName", required: true
    field :last_name, :string, key: "lastName", required: true, default: ""

    has_one :main_address, Address, key: "mainAddress", required: true do
      field :city, :string, required: true
      field :street, :string
      field :number, :integer
    end

    has_many :phones, Phone do
      field :country, :string
      field :number, :integer
    end
  end
end

Another possibility is avoiding creating files for a schema at all. This can be done by importing Parameter.Schema and using the param/2 macro. This is useful for adding params in Phoenix controllers. For example:

defmodule MyProjectWeb.UserController do
  use MyProjectWeb, :controller
  import Parameter.Schema

  alias MyProject.Users

  param UserParams do
    field :first_name, :string, required: true
    field :last_name, :string, required: true
  end

  def create(conn, params) do
    with {:ok, user_params} <- Parameter.load(__MODULE__.UserParams, params),
        {:ok, user} <- Users.create_user(user_params) do
      render(conn, "user.json", %{user: user})
    end
  end
end

It's recommended to use this approach when the schema will only be used in a single module.

runtime-schemas

Runtime Schemas

It's also possible to create schemas via runtime without relying on any macros. The API is almost the same comparing to the macro's examples:

schema = %{
  first_name: [key: "firstName", type: :string, required: true],
  address: [required: true, type: {:has_one, %{street: [type: :string, required: true]}}],
  phones: [type: {:has_many, %{country: [type: :string, required: true]}}]
}

compiled_schema = Parameter.Schema.compile!(schema)

Parameter.load(compiled_schema, %{"firstName" => "John"})
...

The same API can also be evaluated on compile time by using module attributes:

defmodule UserParams do
  alias Parameter.Schema

  @schema %{
    first_name: [key: "firstName", type: :string, required: true],
    address: [required: true, type: {:has_one, %{street: [type: :string, required: true]}}],
    phones: [type: {:has_many, %{country: [type: :string, required: true]}}]
  } |> Schema.compile!()

  def load(params) do
    Parameter.load(@schema, params)
  end
end

This makes it easy to dynamically create schemas or just avoid using any macros.

required-fields

Required fields

By default, Parameter.Schema considers all fields to be optional when validating the schema. This behaviour can be changed by passing the module attribute @fields_required true on the module where the schema is declared.

example

Example

defmodule MyApp.UserSchema do
  use Parameter.Schema

  @fields_required true

  param do
    field :name, :string
    field :age, :integer
  end
end

Parameter.load(MyApp.UserSchema, %{})
{:error, %{age: "is required", name: "is required"}}

Link to this section Summary

Link to this section Functions