Skip to content

Commit 16d7b24

Browse files
committed
go for source_changeset.changes first, fallback to struct field
1 parent 5db99e3 commit 16d7b24

File tree

2 files changed

+101
-49
lines changed

2 files changed

+101
-49
lines changed

lib/polymorphic_embed/html/helpers.ex

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -57,46 +57,70 @@ if Code.ensure_loaded?(Phoenix.HTML) && Code.ensure_loaded?(Phoenix.HTML.Form) d
5757

5858
struct = Ecto.Changeset.apply_changes(source_changeset)
5959

60-
list_data =
61-
case Map.get(struct, field) do
62-
nil ->
63-
type = Keyword.get(options, :polymorphic_type, get_polymorphic_type(form, field))
64-
module = PolymorphicEmbed.get_polymorphic_module(struct.__struct__, field, type)
65-
if module, do: [struct(module)], else: []
66-
67-
data ->
68-
List.wrap(data)
69-
end
70-
71-
list_data
72-
|> Enum.with_index()
73-
|> Enum.map(fn {data, i} ->
74-
params =
75-
case params do
60+
Map.get(source_changeset.changes, field)
61+
|> case do
62+
nil ->
63+
case Map.get(struct, field) do
7664
nil ->
77-
%{}
78-
79-
params when is_list(params) ->
80-
Enum.at(params, i) || %{}
65+
type = Keyword.get(options, :polymorphic_type, get_polymorphic_type(form, field))
66+
module = PolymorphicEmbed.get_polymorphic_module(struct.__struct__, field, type)
67+
if module, do: [struct(module)], else: []
8168

82-
params when is_map(params) ->
83-
Map.get(params, to_string(i), %{})
69+
data ->
70+
List.wrap(data)
8471
end
8572

86-
changeset =
73+
data when is_list(data) ->
8774
data
88-
|> Ecto.Changeset.change()
89-
|> apply_action(parent_action)
9075

91-
errors = get_errors(changeset)
92-
93-
changeset = %Ecto.Changeset{
94-
changeset
95-
| action: parent_action,
96-
params: params,
97-
errors: errors,
98-
valid?: errors == []
99-
}
76+
data ->
77+
List.wrap(data)
78+
end
79+
|> Enum.with_index()
80+
|> Enum.map(fn
81+
{%Ecto.Changeset{} = changeset, i} ->
82+
params = changeset.params || %{}
83+
errors = get_errors(changeset)
84+
85+
%{changeset: changeset, params: params, errors: errors, index: i}
86+
87+
{data, i} ->
88+
params =
89+
case params do
90+
nil ->
91+
%{}
92+
93+
params when is_list(params) ->
94+
Enum.at(params, i) || %{}
95+
96+
params when is_map(params) ->
97+
Map.get(params, to_string(i), %{})
98+
end
99+
100+
changeset =
101+
data
102+
|> Ecto.Changeset.change()
103+
|> apply_action(parent_action)
104+
105+
errors = get_errors(changeset)
106+
107+
changeset = %{
108+
changeset
109+
| action: parent_action,
110+
params: params,
111+
errors: errors,
112+
valid?: errors == []
113+
}
114+
115+
%{changeset: changeset, params: params, errors: errors, index: i}
116+
end)
117+
|> Enum.map(fn prepared_data ->
118+
%{
119+
changeset: changeset,
120+
params: params,
121+
errors: errors,
122+
index: i
123+
} = prepared_data
100124

101125
%schema{} = source_changeset.data
102126

@@ -116,7 +140,8 @@ if Code.ensure_loaded?(Phoenix.HTML) && Code.ensure_loaded?(Phoenix.HTML.Form) d
116140
name: if(array?, do: name <> "[" <> index_string <> "]", else: name),
117141
index: if(array?, do: i),
118142
errors: errors,
119-
data: data,
143+
data: changeset.data,
144+
action: parent_action,
120145
params: params,
121146
hidden: [{type_field_name, to_string(type)}],
122147
options: options

test/polymorphic_embed_test.exs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,15 +2704,26 @@ defmodule PolymorphicEmbedTest do
27042704
for generator <- @generators do
27052705
reminder_module = get_module(Reminder, generator)
27062706

2707-
attrs = %{
2708-
date: ~U[2020-05-28 02:57:19Z],
2709-
text: "This is an Email reminder",
2710-
channel: %{
2711-
address: "a",
2712-
valid: true,
2713-
confirmed: true
2714-
}
2715-
}
2707+
attrs =
2708+
if polymorphic?(generator) do
2709+
%{
2710+
date: ~U[2020-05-28 02:57:19Z],
2711+
text: "This is an Email reminder",
2712+
channel: %{
2713+
address: "a",
2714+
valid: true,
2715+
confirmed: true
2716+
}
2717+
}
2718+
else
2719+
%{
2720+
number: ~U[2020-05-28 02:57:19Z],
2721+
text: "This is a non polymorphic reminder",
2722+
channel: %{
2723+
number: "a"
2724+
}
2725+
}
2726+
end
27162727

27172728
changeset =
27182729
struct(reminder_module)
@@ -2721,8 +2732,19 @@ defmodule PolymorphicEmbedTest do
27212732
contents =
27222733
safe_inputs_for(changeset, :channel, generator, fn f ->
27232734
assert f.impl == Phoenix.HTML.FormData.Ecto.Changeset
2724-
assert f.errors == []
2725-
text_input(f, :address)
2735+
2736+
if polymorphic?(generator) do
2737+
assert f.errors == [
2738+
{:address,
2739+
{"should be at least %{count} character(s)",
2740+
[count: 3, validation: :length, kind: :min, type: :string]}}
2741+
]
2742+
2743+
text_input(f, :address)
2744+
else
2745+
assert f.errors == []
2746+
text_input(f, :number)
2747+
end
27262748
end)
27272749

27282750
expected_contents =
@@ -2732,7 +2754,7 @@ defmodule PolymorphicEmbedTest do
27322754
<input id="reminder_channel_address" name="reminder[channel][address]" type="text" value="a">
27332755
""",
27342756
else: ~s"""
2735-
<input id="reminder_channel_address" name="reminder[channel][address]" type="text" value="a">
2757+
<input id="reminder_channel_number" name="reminder[channel][number]" type="text" value="a">
27362758
"""
27372759
)
27382760

@@ -2745,7 +2767,12 @@ defmodule PolymorphicEmbedTest do
27452767
generator,
27462768
fn f ->
27472769
assert f.impl == Phoenix.HTML.FormData.Ecto.Changeset
2748-
text_input(f, :address)
2770+
2771+
if polymorphic?(generator) do
2772+
text_input(f, :address)
2773+
else
2774+
text_input(f, :number)
2775+
end
27492776
end
27502777
)
27512778

@@ -2756,7 +2783,7 @@ defmodule PolymorphicEmbedTest do
27562783
<input id="reminder_channel_address" name="reminder[channel][address]" type="text" value="a">
27572784
""",
27582785
else: ~s"""
2759-
<input id="reminder_channel_address" name="reminder[channel][address]" type="text" value="a">
2786+
<input id="reminder_channel_number" name="reminder[channel][number]" type="text" value="a">
27602787
"""
27612788
)
27622789

0 commit comments

Comments
 (0)