diff --git a/lib/ecto.ex b/lib/ecto.ex index c3e7bb527d..096de4769d 100644 --- a/lib/ecto.ex +++ b/lib/ecto.ex @@ -723,14 +723,14 @@ defmodule Ecto do @spec embedded_load( module_or_map :: module | map(), data :: map(), - format :: atom() + format :: atom() | (Ecto.Type.t(), term -> {:ok, term} | :error) ) :: Ecto.Schema.t() | map() - def embedded_load(schema_or_types, data, format) do - Ecto.Schema.Loader.unsafe_load( - schema_or_types, - data, - &Ecto.Type.embedded_load(&1, &2, format) - ) + def embedded_load(schema_or_types, data, format) when is_atom(format) do + embedded_load(schema_or_types, data, &Ecto.Type.embedded_load(&1, &2, format)) + end + + def embedded_load(schema_or_types, data, loader) when is_function(loader, 2) do + Ecto.Schema.Loader.unsafe_load(schema_or_types, data, loader) end @doc """ @@ -743,12 +743,15 @@ defmodule Ecto do %{title: "hello"} """ - @spec embedded_dump(Ecto.Schema.t(), format :: atom()) :: map() - def embedded_dump(%schema{} = data, format) do - Ecto.Schema.Loader.safe_dump( - data, - schema.__schema__(:dump), - &Ecto.Type.embedded_dump(&1, &2, format) - ) + @spec embedded_dump( + Ecto.Schema.t(), + format :: atom() | (Ecto.Type.t(), term -> {:ok, term} | :error) + ) :: map() + def embedded_dump(data, format) when is_atom(format) do + embedded_dump(data, &Ecto.Type.embedded_dump(&1, &2, format)) + end + + def embedded_dump(%schema{} = data, dumper) when is_function(dumper, 2) do + Ecto.Schema.Loader.safe_dump(data, schema.__schema__(:dump), dumper) end end diff --git a/test/ecto/embedded_test.exs b/test/ecto/embedded_test.exs index 162107b6c2..f516f54479 100644 --- a/test/ecto/embedded_test.exs +++ b/test/ecto/embedded_test.exs @@ -78,6 +78,13 @@ defmodule Ecto.EmbeddedTest do assert %Settings{dark_mode: false, default_post: nil} = Ecto.embedded_load(Settings, %{"default_post" => nil}, :json) + assert %Settings{dark_mode: false, default_post: nil} = + Ecto.embedded_load( + Settings, + %{"default_post" => nil}, + &Ecto.Type.embedded_load(&1, &2, :json) + ) + assert_raise ArgumentError, ~s[cannot load `"ABC"` as type Ecto.UUID for field `uuid` in schema Ecto.EmbeddedTest.UUIDSchema], fn -> @@ -100,6 +107,12 @@ defmodule Ecto.EmbeddedTest do assert [author1 | _] = dumped.authors assert not Map.has_key?(author1, :__struct__) assert not Map.has_key?(author1, :__meta__) + + assert %{uuid: ^uuid} = + Ecto.embedded_dump( + %UUIDSchema{uuid: uuid}, + &Ecto.Type.embedded_dump(&1, &2, :json) + ) end test "embedded schemas are not queryable" do