defmodule ISN do @behaviour Postgrex.Extension @isn ~w(ean13 isbn13 ismn13 issn13 isbn ismn issn upc) @moduledoc """ A Postgrex.Extension enabling the use of postgresql data types from the isn extension. In lib/ directory create a file with the following content: Postgrex.Types.define( MyApp.PostgrexTypes, [ISN] ++ Ecto.Adapters.Postgres.extensions(), json: Poison ) Add the following lines in conig.exs: config :my_app, MyApp.Repo, types: MyApp.PostgrexTypes Then you can do Ecto.Migrations like this: defmodule MyApp.Repo.Migrations.CreateBook do use Ecto.Migration def change do create table(:books) do add :isbn, :isbn13 # other fields end end end You can also define Ecto.Models using the matching custom Ecto.Types: defmodule MyApp.Book do use MyApp.Web, :model schema "books" do field :isbn, ISN.ISBN13, read_after_writes: true # other fields end end """ def init(opts), do: Keyword.get(opts, :decode_copy, :reference) def matching(_), do: Enum.zip(Stream.cycle([:type]), @isn) def format(_), do: :text def encode(_opts) do quote do thing -> [<> | thing] end end def decode(:copy) do quote do <> -> :binary.copy(thing) end end def decode(:reference) do quote do <> -> thing end end end # Generate Ecto.Type modules for all supported data types in the `isn` # postgresql module. for module <- ~w(ISBN ISMN ISSN ISBN13 ISMN13 ISSN13 UPC EAN13) do module_name = Module.concat([ISN, module]) ecto_type = module |> String.downcase() |> String.to_atom() defmodule module_name do @moduledoc """ Definition for the ISN.#{module} module. How to use this in an Ecto.Model defmodule MyApp.Book do use MyApp.Web, :model schema "books" do field :#{ecto_type}, ISN.#{module} # other fields end end """ use Ecto.Type def type, do: unquote(ecto_type) def cast(nil), do: :error def cast(isn), do: {:ok, to_string(isn)} def load(isn), do: {:ok, to_string(isn)} def dump(isn), do: {:ok, to_string(isn)} end end