-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cast polymorphic embeds #407
Comments
@mathieuprog thanks for opening this. I don't know right now how we could allow customization of the Ecto strategy in order to allow for custom casting of polymorphic embeds. Typically, if we need to change the strategy, I think it's okay to create a custom strategy, like you've done. But I understand the desire to use the default Ecto strategy with some configuration. I'll try to think through and consider if there's a good way to do that. But if you have some idea in mind as to how we could do this, I'd love to hear it. |
Going off of the ecto strategy provided by @mathieuprog, changing the defp cast_polymorphic_embeds(%{__struct__: schema} = struct) do
schema
|> schema_polymorphic_embeds()
|> Enum.reduce(struct, fn embed_key, struct ->
embed_type = schema.__schema__(:type, embed_key)
value = Map.get(struct, embed_key)
casted_value =
case embed_type do
{:parameterized, PolymorphicEmbed, options} ->
load_polymorphic_schema(value, options)
{:array, {:parameterized, PolymorphicEmbed, options}} ->
Enum.map(value, fn el ->
load_polymorphic_schema(el, options)
end)
end
Map.put(struct, embed_key, casted_value)
end)
end
defp load_polymorphic_schema(data, options) do
if is_struct(data) do
data
else
{:ok, embed} = PolymorphicEmbed.load(data, nil, options)
embed
end
end
defp schema_polymorphic_embeds(schema) do
Enum.filter(schema.__schema__(:fields), fn field ->
case schema.__schema__(:type, field) do
{:parameterized, PolymorphicEmbed, _options} -> true
{:array, {:parameterized, PolymorphicEmbed, _options}} -> true
_ -> false
end
end)
end |
A custom strategy here involves copy-pasting the whole Here are 3 possibilities I have thought about: |
@mathieuprog thanks for linking to those potential solutions. I haven't fully considered how we'd implement that in ExMachina's side, but just from looking at the suggestions, I think option 1 would be the easiest to implement, and it would allow for other casting of custom types as people have need. Just quoting here option 1 from your link:
I imagine we could just add one more function at the end of the defp cast(record) do
record
|> cast_all_fields()
|> cast_all_embeds()
|> cast_all_assocs()
|> cast_custom_types()
end
defp cast_custom_types(struct) do
custom_types = Application.get_env(:ex_machina, :cast_custom_types, [])
Enum.reduce(custom_types, struct, fn type_module, struct ->
type_module.cast_custom_type(struct)
end)
end Is that what you had in mind? |
A function This: defp schema_fields(schema) do
(schema_non_virtual_fields(schema) -- schema_embeds(schema))
end needs to be changed to this: defp schema_fields(schema) do
schema_non_virtual_fields(schema) -- schema_embeds(schema) -- # the custom type fields from `schema_custom_types/1`
end
|
Hi, any update on this issue? |
Hello. Any update on this? |
Hi there. Any update on this? It was marked as completed on Jan 17th but I didn't see a PR for it. |
Bump |
@egeersoz I think the following needs to be implemented: #407 (comment) Which involves adding an option in config :ex_machina, :cast_custom_types, MyApp.ExMachina.CastCustomTypes where And Ex Machina needs to use the behaviour at these locations: |
Users of the polymorphic embed library are working with ex_machina for their tests.
The library introduces a new function
cast_polymorphic_embed/2
for casting fields of type{:parameterized, PolymorphicEmbed, options}
.Would it be possible to allow somehow to customize the Ecto strategy in order for us to add the casting of polymorphic embeds?
See here what we'd need to hook into https://github.com/mathieuprog/polymorphic_embed/blob/d1c9b357f81e209858059db210362900ae2186e0/lib/ex_machina/ecto_strategy.ex#L22
("Change Start" - "Change End" blocks)
The text was updated successfully, but these errors were encountered: