krut
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!
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #ai
- #phoenix_html
- #iex
- #graphql
- #elixirconf-us
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 3- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
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_asand:equal?you’ll want to implement those as well or useuse Ecto.Typeinstead of@behaviour Ecto.Typeto have defaults generated.krut
Thanks! I think
use Ecto.Typeis what I was looking for here, since I really only need to cast. Warnings are gone and it’s working greatAetherus
In Ecto 3.x, you can implement
embed_as/1and return:dump. If you do so, Ecto will callYourCustomType.dump/1before JSON serialization when saving embedded schema into DB. On the other hand, ifembed_as/1returns:self, then Ecto won’t calldumpbefore JSON serializing an embed.