I am writing an API integration that uses embedded schemas to cast response data before it is used internally. The id
fields in the responses are typically integers, and I would like them to convert them to strings.
I could transform these values manually, but there are a number of different responses and schemas, all with the same id
format, so I am thinking it could be nice to define a custom type that handles this conversion “behind the scenes”.
I have defined my type as:
defmodule Types.ResponseID do
@behaviour Ecto.Type
def type, do: :string
def cast(integer) when is_integer(integer) do
{ :ok, Integer.to_string(integer) }
end
def cast(string) when is_binary(string), do: { :ok, string }
def cast(_), do: :error
end
And my schema:
defmodule Thing do
use Ecto.Schema
import Ecto.Changeset
@primary_key false
embedded_schema do
field :id, Types.ResponseID
end
def from_response(data) do
%__MODULE__{}
|> Ecto.Changeset.cast(data, [:id])
|> apply_changes()
end
Which then throws these warnings:
warning: function dump/1 required by behaviour Ecto.Type is not implemented (in module ResponseID)
lib/types/response_id.ex:1: ResponseID (module)
warning: function embed_as/1 required by behaviour Ecto.Type is not implemented (in module ResponseID)
lib/types/response_id.ex:1: ResponseID (module)
warning: function equal?/2 required by behaviour Ecto.Type is not implemented (in module ResponseID)
lib/types/response_id.ex:1: ResponseID (module)
warning: function load/1 required by behaviour Ecto.Type is not implemented (in module ResponseID)
lib/types/response_id.ex:1: ResponseID (module)
My question - Do I need to add @behaviour Ecto.Type
for a custom type in an embedded schema? Or is this a better way to define a custom type for this use case?
I found this comment suggesting that the additional behaviors (e.g. load/dump) are not necessary for custom types in embedded schemas, but I haven’t found any documentation showing an example of how to implement:
Thanks!