krut
Using custom type in embedded schema
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!
Marked As Solved
LostKobrakai
The callbacks are still required for the behaviour to be correctly implemented, otherwise you’ll get the warnings you see. They’re just not used for fields in embedded schemas.
Given you also have warnings about :embed_as and :equal? you’ll want to implement those as well or use use Ecto.Type instead of @behaviour Ecto.Type to have defaults generated.
Also Liked
Aetherus
In Ecto 3.x, you can implement embed_as/1 and return :dump. If you do so, Ecto will call YourCustomType.dump/1 before JSON serialization when saving embedded schema into DB. On the other hand, if embed_as/1 returns :self, then Ecto won’t call dump before JSON serializing an embed.







