Skip to content

Commit 4757cb5

Browse files
committed
Allow virtual embeds
1 parent 3a397bf commit 4757cb5

File tree

4 files changed

+28
-7
lines changed

4 files changed

+28
-7
lines changed

lib/ecto/embedded.ex

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ defmodule Ecto.Embedded do
2828
:owner,
2929
:related,
3030
:on_cast,
31+
virtual: false,
3132
on_replace: :raise,
3233
unique: true,
3334
ordered: true
@@ -149,7 +150,11 @@ defmodule Ecto.Embedded do
149150
@doc false
150151
def prepare(changeset, embeds, adapter, repo_action) do
151152
%{changes: changes, types: types, repo: repo} = changeset
152-
prepare(Map.take(changes, embeds), types, adapter, repo, repo_action)
153+
#non_virtual_embeds = Enum.reject(embeds, & &1.virtual)
154+
155+
changes
156+
|> Map.take(embeds)
157+
|> prepare(types, adapter, repo, repo_action)
153158
end
154159

155160
defp prepare(embeds, _types, _adapter, _repo, _repo_action) when embeds == %{} do
@@ -158,9 +163,15 @@ defmodule Ecto.Embedded do
158163

159164
defp prepare(embeds, types, adapter, repo, repo_action) do
160165
Enum.reduce(embeds, embeds, fn {name, changeset_or_changesets}, acc ->
161-
{:embed, embed} = Map.get(types, name)
162-
Map.put(acc, name, prepare_each(embed, changeset_or_changesets, adapter, repo, repo_action))
163-
end)
166+
case Map.get(types, name) do
167+
{:embed, %{virtual: false} = embed} ->
168+
prepared = prepare_each(embed, changeset_or_changesets, adapter, repo, repo_action)
169+
Map.put(acc, name, prepared)
170+
171+
{:embed, %{virtual: true}} ->
172+
acc
173+
end)
174+
end
164175
end
165176

166177
defp prepare_each(%{cardinality: :one}, nil, _adapter, _repo, _repo_action) do

lib/ecto/schema.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,7 +2143,7 @@ defmodule Ecto.Schema do
21432143
Module.put_attribute(mod, :ecto_changeset_fields, {name, {:assoc, struct}})
21442144
end
21452145

2146-
@valid_embeds_one_options [:on_replace, :source, :load_in_query, :defaults_to_struct]
2146+
@valid_embeds_one_options [:on_replace, :source, :load_in_query, :defaults_to_struct, :virtual]
21472147

21482148
@doc false
21492149
def __embeds_one__(mod, name, schema, opts) when is_atom(schema) do
@@ -2164,7 +2164,7 @@ defmodule Ecto.Schema do
21642164
"`embeds_one/3` expects `schema` to be a module name, but received #{inspect(schema)}"
21652165
end
21662166

2167-
@valid_embeds_many_options [:on_replace, :source, :load_in_query]
2167+
@valid_embeds_many_options [:on_replace, :source, :load_in_query, :virtual]
21682168

21692169
@doc false
21702170
def __embeds_many__(mod, name, schema, opts) when is_atom(schema) do

test/ecto/embedded_test.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ defmodule Ecto.EmbeddedTest do
1919
field :name, :string
2020
embeds_one :profile, Profile, on_replace: :delete
2121
embeds_one :post, Post
22+
embeds_one :virtual_post, Post, virtual: true
2223
embeds_many :posts, Post, on_replace: :delete
2324
end
2425
end
@@ -45,7 +46,7 @@ defmodule Ecto.EmbeddedTest do
4546

4647
test "__schema__" do
4748
assert Author.__schema__(:embeds) ==
48-
[:profile, :post, :posts]
49+
[:profile, :post, :virtual_post, :posts]
4950

5051
assert Author.__schema__(:embed, :profile) ==
5152
%Embedded{field: :profile, cardinality: :one, owner: Author, on_replace: :delete, related: Profile}

test/ecto/repo_test.exs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,15 @@ defmodule Ecto.RepoTest do
160160
end
161161
end
162162

163+
defmodule MySchemaVirtualEmbed do
164+
use Ecto.Schema
165+
166+
schema "my_schema" do
167+
field :x, :string
168+
embeds_one :virtual_embed, MyEmbed, virtual: true
169+
end
170+
end
171+
163172
defmodule MySchemaNoPK do
164173
use Ecto.Schema
165174

0 commit comments

Comments
 (0)