Ecto.ParameterizedType behaviour (Ecto v3.5.4) View Source

Parameterized types are Ecto types that can be customized per field.

Parameterized types allow a set of options to be specified in the schema which are initialized on compilation and passed to the callback functions as the last argument.

For example, field :foo, :string behaves the same for every field. On the other hand, field :foo, Ecto.Enum, values: [:foo, :bar, :baz] will likely have a different set of values per field.

Note that options are specified as a keyword, but it is idiomatic to convert them to maps inside init/1 for easier pattern matching in other callbacks.

Parameterized types are a superset of regular types. In other words, with parameterized types you can do everything a regular type does, and more. For example, parameterized types can handle nil values in both load and dump callbacks, they can customize cast behavior per query and per changeset, and also control how values are embedded.

However, parameterized types are also more complex. Therefore, if everything you need to achieve can be done with basic types, they should be preferred to parameterized ones.

Examples

To create a parameterized type, create a module as shown below:

defmodule MyApp.MyType do
  use Ecto.ParameterizedType

  def type(_params), do: :string

  def init(opts) do
    validate_opts(opts)
    Enum.into(opts, %{})
  end

  def cast(data, params) do
    ...
    cast_data
  end

  def load(data, _loader, params) do
    ...
    {:ok, loaded_data}
  end

  def dump(data, dumper, params) do
    ...
    {:ok, dumped_data}
  end

  def equal?(a, b, _params) do
    a == b
  end
end

To use this type in a schema field, specify the type and parameters like this:

schema "foo" do
  field :bar, MyApp.MyType, opt1: :baz, opt2: :boo
end

Link to this section Summary

Types

The keyword options passed from the Schema's field macro into init/1

The parameters for the ParameterizedType

Callbacks

Generates a loaded version of the data.

Casts the given input to the ParameterizedType with the given parameters.

Dumps the given term into an Ecto native type.

Dictates how the type should be treated inside embeds.

Checks if two terms are semantically equal.

Callback to convert the options specified in the field macro into parameters to be used in other callbacks.

Loads the given term into a ParameterizedType.

Returns the underlying schema type for the ParameterizedType.

Link to this section Types

Specs

opts() :: keyword()

The keyword options passed from the Schema's field macro into init/1

Specs

params() :: term()

The parameters for the ParameterizedType

This is the value passed back from init/1 and subsequently passed as the last argument to all callbacks. Idiomatically it is a map.

Link to this section Callbacks

Link to this callback

autogenerate(params)

View Source (optional)

Specs

autogenerate(params()) :: term()

Generates a loaded version of the data.

This is callback is invoked when a parameterized type is given to field with the :autogenerate flag.

Specs

cast(data :: term(), params()) :: {:ok, term()} | :error | {:error, keyword()}

Casts the given input to the ParameterizedType with the given parameters.

If the parameterized type is also a composite type, the inner type can be cast by calling Ecto.Type.cast/2 directly.

For more information on casting, see Ecto.Type.cast/1.

Link to this callback

dump(value, dumper, params)

View Source

Specs

dump(value :: any(), dumper :: function(), params()) ::
  {:ok, value :: any()} | :error

Dumps the given term into an Ecto native type.

It receives a dumper function in case the parameterized type is also a composite type. In order to dump the inner type, the dumper must be called with the inner type and the inner value as argument.

For more information on dumping, see Ecto.Type.dump/1. Note that this callback will be called when dumping a nil value, unlike Ecto.Type.dump/1.

Link to this callback

embed_as(format, params)

View Source

Specs

embed_as(format :: atom(), params()) :: :self | :dump

Dictates how the type should be treated inside embeds.

For more information on embedding, see Ecto.Type.embed_as/1

Link to this callback

equal?(value1, value2, params)

View Source

Specs

equal?(value1 :: any(), value2 :: any(), params()) :: boolean()

Checks if two terms are semantically equal.

Specs

init(opts :: opts()) :: params()

Callback to convert the options specified in the field macro into parameters to be used in other callbacks.

This function is called at compile time, and should raise if invalid values are specified. It is idiomatic that the parameters returned from this are a map. field and schema will be injected into the options automatically.

For example, this schema specification

schema "my_table" do
  field :my_field, MyParameterizedType, opt1: :foo, opt2: nil
end

will result in the call:

MyParameterizedType.init([schema: "my_table", field: :my_field, opt1: :foo, opt2: nil])
Link to this callback

load(value, loader, params)

View Source

Specs

load(value :: any(), loader :: function(), params()) ::
  {:ok, value :: any()} | :error

Loads the given term into a ParameterizedType.

It receives a loader function in case the parameterized type is also a composite type. In order to load the inner type, the loader must be called with the inner type and the inner value as argument.

For more information on loading, see Ecto.Type.load/1. Note that this callback will be called when loading a nil value, unlike Ecto.Type.load/1.

Specs

type(params()) :: Ecto.Type.t()

Returns the underlying schema type for the ParameterizedType.

For more information on schema types, see Ecto.Type.type/0