Skip to content

Commit

Permalink
surface embed data on insert
Browse files Browse the repository at this point in the history
  • Loading branch information
greg-rychlewski committed Sep 15, 2023
1 parent 22b2d3c commit 69c0167
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 12 deletions.
16 changes: 5 additions & 11 deletions lib/ecto/embedded.ex
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,14 @@ defmodule Ecto.Embedded do
end

defp prepare_each(%{cardinality: :one} = embed, changeset, adapter, repo, repo_action) do
action = check_action!(changeset.action, repo_action, embed)
action = normalize_action(changeset.action, repo_action, embed)
changeset = run_prepare(changeset, repo)
to_struct(changeset, action, embed, adapter)
end

defp prepare_each(%{cardinality: :many} = embed, changesets, adapter, repo, repo_action) do
for changeset <- changesets,
action = check_action!(changeset.action, repo_action, embed),
action = normalize_action(changeset.action, repo_action, embed),
changeset = run_prepare(changeset, repo),
prepared = to_struct(changeset, action, embed, adapter),
do: prepared
Expand Down Expand Up @@ -244,15 +244,9 @@ defmodule Ecto.Embedded do
struct(struct, changes)
end

defp check_action!(:replace, action, %{on_replace: :delete} = embed),
do: check_action!(:delete, action, embed)

defp check_action!(:update, :insert, %{related: schema}) do
raise ArgumentError,
"got action :update in changeset for embedded #{inspect(schema)} while inserting"
end

defp check_action!(action, _, _), do: action
defp normalize_action(:replace, _, %{on_replace: :delete}), do: :delete
defp normalize_action(:update, :insert, _), do: :insert
defp normalize_action(action, _, _), do: action

defp autogenerate_id(changes, _struct, :insert, schema, adapter) do
case schema.__schema__(:autogenerate_id) do
Expand Down
31 changes: 30 additions & 1 deletion test/ecto/repo_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ defmodule Ecto.RepoTest do
embedded_schema do
field :x, :string
end

def changeset(struct, params) do
Ecto.Changeset.cast(struct, params, [:x])
end
end

defmodule MySchemaChild do
Expand Down Expand Up @@ -131,7 +135,7 @@ defmodule Ecto.RepoTest do

schema "my_schema" do
field :x, :string
embeds_many :embeds, MyEmbed
embeds_many :embeds, MyEmbed, on_replace: :delete
end
end

Expand Down Expand Up @@ -1196,6 +1200,31 @@ defmodule Ecto.RepoTest do
TestRepo.insert_or_update %MySchema{}
end
end

test "insert surfaces embed fields" do
# embeds_one
inserted =
%MySchemaEmbedsOne{embed: %MyEmbed{x: "old"}}
|> Ecto.Changeset.cast(%{embed: %{x: "update"}}, [])
|> Ecto.Changeset.cast_embed(:embed)
|> TestRepo.insert!()

assert inserted.embed.x == "update"

# embeds_many
data_embed1 = %MyEmbed{id: 1, x: "old1"}
data_embed2 = %MyEmbed{id: 2, x: "old2"}

inserted =
%MySchemaEmbedsMany{embeds: [data_embed1, data_embed2]}
|> Ecto.Changeset.cast(%{embeds: [%{id: 1, x: "update"}, %{}]}, [])
|> Ecto.Changeset.cast_embed(:embeds)
|> TestRepo.insert!()

%{embeds: inserted_embeds} = inserted
assert [%{id: 1, x: "update"}, %{id: new_id, x: nil}] = inserted_embeds
assert new_id != data_embed2.id
end
end

test "get, get_by, one and all sets schema prefix" do
Expand Down

0 comments on commit 69c0167

Please sign in to comment.