Skip to content

Commit 3383f02

Browse files
committed
Allow virtual embeds
1 parent 0917cbb commit 3383f02

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

lib/ecto/embedded.ex

Lines changed: 14 additions & 3 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
@@ -144,7 +145,11 @@ defmodule Ecto.Embedded do
144145
@doc false
145146
def prepare(changeset, embeds, adapter, repo_action) do
146147
%{changes: changes, types: types, repo: repo} = changeset
147-
prepare(Map.take(changes, embeds), types, adapter, repo, repo_action)
148+
#non_virtual_embeds = Enum.reject(embeds, & &1.virtual)
149+
150+
changes
151+
|> Map.take(embeds)
152+
|> prepare(types, adapter, repo, repo_action)
148153
end
149154

150155
defp prepare(embeds, _types, _adapter, _repo, _repo_action) when embeds == %{} do
@@ -153,8 +158,14 @@ defmodule Ecto.Embedded do
153158

154159
defp prepare(embeds, types, adapter, repo, repo_action) do
155160
Enum.reduce embeds, embeds, fn {name, changeset_or_changesets}, acc ->
156-
{:embed, embed} = Map.get(types, name)
157-
Map.put(acc, name, prepare_each(embed, changeset_or_changesets, adapter, repo, repo_action))
161+
case Map.get(types, name) do
162+
{:embed, %{virtual: false} = embed} ->
163+
prepared = prepare_each(embed, changeset_or_changesets, adapter, repo, repo_action)
164+
Map.put(acc, name, prepared)
165+
166+
{:embed, %{virtual: true}} ->
167+
acc
168+
end
158169
end
159170
end
160171

lib/ecto/schema.ex

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

2089-
@valid_embeds_one_options [:on_replace, :source]
2089+
@valid_embeds_one_options [:on_replace, :source, :virtual]
20902090

20912091
@doc false
20922092
def __embeds_one__(mod, name, schema, opts) when is_atom(schema) do
@@ -2099,7 +2099,7 @@ defmodule Ecto.Schema do
20992099
"`embeds_one/3` expects `schema` to be a module name, but received #{inspect(schema)}"
21002100
end
21012101

2102-
@valid_embeds_many_options [:on_replace, :source]
2102+
@valid_embeds_many_options [:on_replace, :source, :virtual]
21032103

21042104
@doc false
21052105
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
@@ -36,7 +37,7 @@ defmodule Ecto.EmbeddedTest do
3637

3738
test "__schema__" do
3839
assert Author.__schema__(:embeds) ==
39-
[:profile, :post, :posts]
40+
[:profile, :post, :virtual_post, :posts]
4041

4142
assert Author.__schema__(:embed, :profile) ==
4243
%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
@@ -134,6 +134,15 @@ defmodule Ecto.RepoTest do
134134
end
135135
end
136136

137+
defmodule MySchemaVirtualEmbed do
138+
use Ecto.Schema
139+
140+
schema "my_schema" do
141+
field :x, :string
142+
embeds_one :virtual_embed, MyEmbed, virtual: true
143+
end
144+
end
145+
137146
defmodule MySchemaNoPK do
138147
use Ecto.Schema
139148

0 commit comments

Comments
 (0)