Atoms and Ecto custom types

Published on 2021-01-04

3m read
elixir, functional programming, ecto

Working on I ran into an issue trying to save an embedded schema like:

defmodule Result do
  embedded_schema do
    field :status, CheckStatusEnum
    field :code, :string
    field :message, :string
    field :payload, :map

Which was failing with the following error:

   action: :insert,
   changes: %{
         errors: [code: {"is invalid", [type: :string, validation: :cast]}],
         data: #Result<>,
         valid?: false

So Ecto will by default not handle the atom passed as the attributes for the result. The solution happened to be pretty straightforward, define a custom Ecto type to handle atoms:

defmodule Siteguardian.Util.AtomType do
  @moduledoc false
  use Ecto.Type
  def type, do: :string
  def cast(value), do: {:ok, value}
  def load(value), do: {:ok, String.to_atom(value)}
  def dump(value) when is_atom(value), do: {:ok, Atom.to_string(value)}
  def dump(_), do: :error

The magic here happens on the dump/1 and load/1 functions; convert atom to string on the way in and convert string to atom on the way out.


What do you think of what I said?

Share with me your thoughts. You can tweet me at @allanmacgregor.