@alexcastano Of course it’s possible, but ecto itself does not helps in complex polymorphic use cases, so you would need to write it yourself.
First of all you would need to have your JSON like:
{"data": …, "type": "your_type_name"}
For it you would need to create a custom Ecto.Type. For each callback you need to check type field and based on it you would need to create n number of modules which also implements Ecto.Type.
Let’s say:
defmodule MyApp.EctoTypes.MainJSON do
use Ecto.Type
def ecto_callback(%{data: data, type: type}) do
with {:ok, result} <- type |> find_module() |> :apply(:ecto_callback, [data]) do
%{data: result, type: type}
end
end
defp find_module("first_type"), do: MyApp.EctoTypes.FirstType
defp find_module("second_type"), do: MyApp.EctoTypes.SecondType
defp find_module("third_type"), do: MyApp.EctoTypes.ThirdType
end
defmodule MyApp.EctoTypes.FirstType do
# no need to use Ecto.Type here
# as this those "sub types" would be used only for Kernel.apply/3
# in order to simply separate code for each type
def ecto_callback(data) do
# …
end
end
In such way you can simply write a code for each type. You only need to implement each Ecto.Type required callback (cast, dump and load if I remember correctly).
If you do this all you need to do (like migrations) is exactly the same as with embeds_many or embeds_one. I wrote all from memory, but it should work even with arrays.
defmodule MyApp.MyContext.MySchema do
alias MyApp.EctoTypes.MainJSON
schema "table_name" do
…
field(:field_name, {:array, MainJSON})
…
end
end
The only difference is that you no longer need to call cast_embed and related functions as everything would be handled in cast.






















