Ecto.Type

Parsed documentation:
View on GitHub
Defines functions and the `Ecto.Type` behaviour for implementing
custom types.

A custom type expects 4 functions to be implemented, all documented
and described below. We also provide two examples of how custom
types can be used in Ecto to augment existing types or providing
your own types.

## Augmenting types

Imagine you want to support your id field to be looked up as a
permalink. For example, you want the following query to work:

    permalink = "10-how-to-be-productive-with-elixir"
    from p in Post, where: p.id == ^permalink

If `id` is an integer field, Ecto will fail in the query above
because it cannot cast the string to an integer. By using a
custom type, we can provide special casting behaviour while
still keeping the underlying Ecto type the same:

    defmodule Permalink do
      def type, do: :integer

      # Provide our own casting rules.
      def cast(string) when is_binary(string) do
        case Integer.parse(string) do
          {int, _} -> {:ok, int}
          :error   -> :error
        end
      end

      # We should still accept integers
      def cast(integer) when is_integer(integer), do: {:ok, integer}

      # Everything else is a failure though
      def cast(_), do: :error

      # When loading data from the database, we are guaranteed to
      # receive an integer (as database are stricts) and we will
      # just return it to be stored in the model struct.
      def load(integer) when is_integer(integer), do: {:ok, integer}

      # When dumping data to the database, we *expect* an integer
      # but any value could be inserted into the struct, so we need
      # guard against them.
      def dump(integer) when is_integer(integer), do: {:ok, integer}
      def dump(_), do: :error
    end

Now, we can use our new field above as our primary key type in models:

    defmodule Post do
      use Ecto.Model

      @primary_key {:id, Permalink, autogenerate: true}
      schema "posts" do
        ...
      end
    end

## New types

In the previous example, we say we were augmenting an existing type
because we were keeping the underlying representation the same, the
value stored in the struct and the database was always an integer.

However, sometimes, we want to completely replace Ecto data types
stored in the models. This is for example how Ecto provides the
`Ecto.DateTime` struct as a replacement for the `:datetime` type.

Check the `Ecto.DateTime` implementation for an example on how
to implement such types.
No suggestions.
Please help! Open an issue on GitHub if this assessment is incorrect.