Skip to content

Commit

Permalink
Fix merging of embed fields
Browse files Browse the repository at this point in the history
  • Loading branch information
cichacz committed Dec 3, 2024
1 parent f27c95e commit 3f6f0fe
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 6 deletions.
14 changes: 11 additions & 3 deletions lib/ecto_discriminator/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ defmodule EctoDiscriminator.Schema do
{field_type, meta, [name, existing_type | existing_rest]} ->
# otherwise in case of conflict and matching types, merge options
if Macro.expand(type, __ENV__) == Macro.expand(existing_type, __ENV__) do
rest = merge_rest_options(existing_rest, List.first(rest) || [])
rest = merge_rest_options(existing_rest, rest)
add_duplicate_meta({field_type, meta, [name, type | rest]})
else
new
Expand Down Expand Up @@ -349,11 +349,19 @@ defmodule EctoDiscriminator.Schema do
update_in(ast, [Access.elem(1)], &Keyword.put(&1, :duplicate, true))
end

defp merge_rest_options(rest, opts) when is_list(opts) do
defp merge_rest_options(rest, opts) do
{opts, opts_rest} =
case opts do
[op | rest] -> {op, rest}
op -> {op, []}
end

opts = List.wrap(opts)

case rest do
[] when opts == [] -> []
[] -> [opts]
[existing] -> [Keyword.merge(existing, opts)]
[existing | _] -> [Keyword.merge(existing, opts) | opts_rest]
end
end

Expand Down
2 changes: 1 addition & 1 deletion test/ecto_discriminator/discriminator_changeset_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ defmodule EctoDiscriminator.DiscriminatorChangesetTest do
source: "asdf",
is_special: true,
type: SomeTable.Qux,
content: %{length: 7}
content: %{text: "abc"}
})
|> Ecto.Changeset.apply_action!(:insert)

Expand Down
2 changes: 1 addition & 1 deletion test/ecto_discriminator/schema_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ defmodule EctoDiscriminator.SchemaTest do
SomeTable.Quux.changeset(%SomeTable.Quux{}, %{
title: :a,
source: "qux",
content: %{length: 3},
content: %{quux_text: "abc"},
is_special: false,
is_last: true
})
Expand Down
11 changes: 11 additions & 0 deletions test/support/some_table/quux.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,22 @@ defmodule EctoDiscriminator.SomeTable.Quux do
# make sure field types can contain calls on module attributes
field :title, Ecto.Enum, values: Keyword.keys(@values)
field :is_last, :boolean, virtual: true

embeds_one :content, Content, primary_key: false, on_replace: :update do
field :quux_text, :string
end
end

def changeset(struct, params \\ %{}) do
struct
|> cast_base(params)
|> cast(params, [:title])
|> cast_embed(:content, required: true, with: &content_changeset/2)
end

def content_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:quux_text])
|> validate_required([:quux_text])
end
end
11 changes: 11 additions & 0 deletions test/support/some_table/qux.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,23 @@ defmodule EctoDiscriminator.SomeTable.Qux do
# make sure base schemas can be referenced using alias
schema Foo do
field :is_special, :boolean

embeds_one :content, Content, primary_key: false, on_replace: :update do
field :text, :string
end
end

def changeset(struct, params \\ %{}) do
struct
|> cast_base(params)
|> cast(params, [:is_special])
|> cast_embed(:content, required: true, with: &content_changeset/2)
|> validate_required([:is_special])
end

def content_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:text])
|> validate_required([:text])
end
end
5 changes: 4 additions & 1 deletion test/support/some_table_pk.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ defmodule EctoDiscriminator.SomeTablePk do
# make sure field types can contain aliases and module attributes
field :title, Enum, values: @values

belongs_to :not_pk, EctoDiscriminator.SomeTable, foreign_key: :type, references: :type, define_field: false
belongs_to :not_pk, EctoDiscriminator.SomeTable,
foreign_key: :type,
references: :type,
define_field: false
end

def changeset(struct, params \\ %{}) do
Expand Down

0 comments on commit 3f6f0fe

Please sign in to comment.