Skip to content

Commit

Permalink
Make it work for embeds without ids
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieuprog committed May 25, 2024
1 parent 9bc13e2 commit 6681c06
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 4 deletions.
8 changes: 6 additions & 2 deletions lib/polymorphic_embed.ex
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,12 @@ defmodule PolymorphicEmbed do

module ->
data_for_field =
Enum.find(list_data_for_field, fn datum ->
datum.id != nil and datum.id == params[:id] and datum.__struct__ == module
Enum.find(list_data_for_field, fn
%{id: id} = datum when not is_nil(id) ->
id == params[:id] and datum.__struct__ == module

_ ->
nil
end)

embed_changeset =
Expand Down
41 changes: 39 additions & 2 deletions test/polymorphic_embed_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,18 @@ defmodule PolymorphicEmbedTest do
age: "aquarius",
address: "address"
}
],
contexts3: [
%{
__type__: "device",
ref: "12345",
type: "cellphone"
},
%{
__type__: "device",
ref: "56789",
type: "laptop"
}
]
}

Expand All @@ -1212,7 +1224,11 @@ defmodule PolymorphicEmbedTest do
|> Repo.insert!()

Enum.each(reminder.contexts, fn context ->
assert context.id
assert Map.has_key?(context, :id)
end)

Enum.each(reminder.contexts3, fn context ->
refute Map.has_key?(context, :id)
end)

reminder =
Expand All @@ -1223,7 +1239,7 @@ defmodule PolymorphicEmbedTest do
assert reminder.contexts |> length() == 2

Enum.each(reminder.contexts, fn context ->
assert context.id
assert Map.has_key?(context, :id)
end)

if polymorphic?(generator) do
Expand Down Expand Up @@ -1286,6 +1302,27 @@ defmodule PolymorphicEmbedTest do

assert Enum.at(reminder.contexts, 0).id == Enum.at(updated_reminder.contexts, 0).id
assert Enum.at(reminder.contexts, 1).id != Enum.at(updated_reminder.contexts, 1).id

# Make sure it also works for embeds without ids (`@primary_key false`)
attrs = %{
contexts3: [
%{
__type__: "device",
ref: "12345",
type: "cellphone"
},
%{
__type__: "device",
ref: "56789",
type: "laptop"
}
]
}

assert {:ok, _} =
reminder
|> reminder_module.changeset(attrs)
|> Repo.update()
end
end

Expand Down
1 change: 1 addition & 0 deletions test/support/migrations/20000101000000_create_tables.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ defmodule PolymorphicEmbed.CreateTables do
add(:channel3, :map)
add(:contexts, :map)
add(:contexts2, :map)
add(:contexts3, :map)

timestamps()
end
Expand Down
5 changes: 5 additions & 0 deletions test/support/models/not_polymorphic/reminder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ defmodule PolymorphicEmbed.Regular.Reminder do
on_replace: :delete
)

embeds_many(:contexts3, PolymorphicEmbed.Regular.Reminder.Context.DeviceNoId,
on_replace: :delete
)

timestamps()
end

Expand All @@ -22,6 +26,7 @@ defmodule PolymorphicEmbed.Regular.Reminder do
|> validate_required(:date)
|> cast_embed(:channel)
|> cast_embed(:contexts)
|> cast_embed(:contexts3)
end

def custom_changeset(struct, attrs) do
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule PolymorphicEmbed.Regular.Reminder.Context.DeviceNoId do
use Ecto.Schema
import Ecto.Changeset

@primary_key false

embedded_schema do
field :ref, :string
field :type, :string

embeds_one :extra, Extra do
field :imei, :string
end
end

def changeset(struct, params) do
struct
|> cast(params, ~w(ref type)a)
|> validate_required(~w(type)a)
end
end
10 changes: 10 additions & 0 deletions test/support/models/polymorphic/reminder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ defmodule PolymorphicEmbed.Reminder do
on_replace: :delete
)

polymorphic_embeds_many(:contexts3,
types: [
location: PolymorphicEmbed.Reminder.Context.Location,
age: PolymorphicEmbed.Reminder.Context.Age,
device: PolymorphicEmbed.Reminder.Context.DeviceNoId
],
on_replace: :delete
)

timestamps()
end

Expand All @@ -66,6 +75,7 @@ defmodule PolymorphicEmbed.Reminder do
|> cast_polymorphic_embed(:channel)
|> cast_polymorphic_embed(:contexts)
|> cast_polymorphic_embed(:contexts2)
|> cast_polymorphic_embed(:contexts3)
end

def custom_changeset(struct, values) do
Expand Down
21 changes: 21 additions & 0 deletions test/support/models/polymorphic/reminder/context/device_no_id.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule PolymorphicEmbed.Reminder.Context.DeviceNoId do
use Ecto.Schema
import Ecto.Changeset

@primary_key false

embedded_schema do
field :ref, :string
field :type, :string

embeds_one :extra, Extra do
field :imei, :string
end
end

def changeset(struct, params) do
struct
|> cast(params, ~w(ref type)a)
|> validate_required(~w(type)a)
end
end

0 comments on commit 6681c06

Please sign in to comment.