Skip to content

Commit

Permalink
Make behavior consistent with embeds_one and force a new `:on_replace…
Browse files Browse the repository at this point in the history
…` option to `:update`
  • Loading branch information
mathieuprog committed Dec 23, 2020
1 parent 6eeb88a commit 8ff4684
Show file tree
Hide file tree
Showing 16 changed files with 512 additions and 263 deletions.
26 changes: 12 additions & 14 deletions lib/polymorphic_embed.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ defmodule PolymorphicEmbed do

@impl true
def init(opts) do
if Keyword.get(opts, :on_replace) != :update do
raise("`:on_replace` option for polymorphic embed must be set to `:update`")
end

metadata =
Keyword.fetch!(opts, :types)
|> Enum.map(fn
Expand Down Expand Up @@ -53,7 +57,7 @@ defmodule PolymorphicEmbed do
nil -> %{}
struct -> map_from_struct(struct, metadata)
end
|> Map.merge(params_for_field || %{})
|> Map.merge(params_for_field)
|> convert_map_keys_to_string()

case do_get_polymorphic_module(params, metadata) do
Expand All @@ -64,9 +68,7 @@ defmodule PolymorphicEmbed do
Ecto.Changeset.add_error(changeset, field, "is invalid")

module ->
module
|> struct()
|> cast_to_changeset(params)
module.changeset(struct(module), params)
|> case do
%{valid?: true} = embed_changeset ->
Ecto.Changeset.put_change(
Expand All @@ -77,8 +79,8 @@ defmodule PolymorphicEmbed do

%{valid?: false} = embed_changeset ->
changeset
|> Ecto.Changeset.put_change(field, Ecto.Changeset.apply_changes(embed_changeset))
|> Ecto.Changeset.add_error(field, "is invalid", embed_changeset.errors)
|> Ecto.Changeset.put_change(field, embed_changeset)
|> Map.put(:valid?, false)
end
end
end
Expand All @@ -94,14 +96,6 @@ defmodule PolymorphicEmbed do
@impl true
def embed_as(_format, _params), do: :dump

defp cast_to_changeset(%module{} = struct, attrs) do
if function_exported?(module, :changeset, 2) do
module.changeset(struct, attrs)
else
Ecto.Changeset.cast(struct, attrs, module.__schema__(:fields))
end
end

@impl true
def load(nil, _loader, _params), do: {:ok, nil}

Expand All @@ -113,6 +107,10 @@ defmodule PolymorphicEmbed do
end

@impl true
def dump(%Ecto.Changeset{valid?: false}, _dumper, _params) do
raise "cannot dump invalid changeset"
end

def dump(%_module{} = struct, dumper, %{metadata: metadata}) do
dumper.(:map, map_from_struct(struct, metadata))
end
Expand Down
Loading

0 comments on commit 8ff4684

Please sign in to comment.