-
Notifications
You must be signed in to change notification settings - Fork 18
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
Third party Module type #40
Comments
Is it a compile error? Can you reproduce it in a livebook? Because I can't, here's what I tried Untitled notebookMix.install([{:typed_ecto_schema, "~> 0.4.1"}, {:polymorphic_embed, "~> 3.0"}])
Sectiondefmodule Foo do
use TypedEctoSchema
import PolymorphicEmbed
typed_schema "todos" do
field(:content, :string)
field(:title, :string)
polymorphic_embeds_one(:form,
types: [
product_form: Todos.ProductForm
],
on_type_not_found: :raise,
on_replace: :update
)
end
end
|
Hello @dvic, thanks for the response. Mix.install([
{:domo, "~> 1.5"},
{:typed_ecto_schema, "~> 0.4.1"},
{:polymorphic_embed, "~> 3.0"}
]) defmodule Foo do
use Domo, skip_defaults: true
use TypedEctoSchema
import PolymorphicEmbed
typed_schema "todos" do
field(:content, :string)
field(:title, :string)
polymorphic_embeds_one(:form,
types: [
product_form: Todos.ProductForm
],
on_type_not_found: :raise,
on_replace: :update
)
end
end |
Ok @drselump14, I experimented a little bit with this and there is a workaround, here is the analysis: TypedEctoSchema + PolymorphicEmbed + DomoMix.install([
{:domo, "~> 1.5"},
{:typed_ecto_schema, "~> 0.4.1"},
{:polymorphic_embed, "~> 3.0"}
])
Analysis and Workarounddefmodule Example1 do
use TypedEctoSchema
import PolymorphicEmbed
typed_schema "todos" do
field(:content, :string)
field(:title, :string)
polymorphic_embeds_one(:form,
types: [
product_form: Todos.ProductForm
],
on_type_not_found: :raise,
on_replace: :update
)
end
end
Ok, let's first understand what's happening on the example by checking the generated type import IEx.Helpers
t(Example1.t())
This is happening because defmodule Example2 do
use TypedEctoSchema
typed_schema "todos" do
field(:content, :string)
field(:title, :string)
field(:form, PolymorphicEmbed,
types: [
product_form: Todos.ProductForm
],
on_type_not_found: :raise,
on_replace: :update
)
end
end
t(Example2.t())
Of course, when creating defmodule Example3 do
use TypedEctoSchema
typed_schema "todos" do
field(:content, :string)
field(:title, :string)
field(:form, PolymorphicEmbed,
types: [
product_form: Todos.ProductForm
],
on_type_not_found: :raise,
on_replace: :update
) :: map() | nil
end
end
t(Example3.t())
With that in mind, a workaround would be: defmodule Example4 do
use TypedEctoSchema
use Domo, skip_defaults: true
typed_schema "todos" do
field(:content, :string)
field(:title, :string)
field(:form, PolymorphicEmbed,
types: [
product_form: Todos.ProductForm
],
on_type_not_found: :raise,
on_replace: :update
) :: map() | nil
end
end
t(Example4.t())
One important detail is that for the workaround to replicate defmodule Example5 do
use TypedEctoSchema
use Domo, skip_defaults: true
typed_schema "todos" do
field(:content, :string)
field(:title, :string)
field(:form, {:array, PolymorphicEmbed},
types: [
product_form: Todos.ProductForm
],
on_type_not_found: :raise,
on_replace: :update,
default: []
) :: [map()]
end
end
t(Example5.t())
Going forwardOf course there are a few things we could do to make this integration a little bit better. Here are some of my ideas (none decided yet):
The trade-offs for me are:
I like the PolymorphicEmbed library so I'd be ok doing |
Nice write up @bamorim !
can't we just expand a known list of macro's while evaluation the entries? (like |
Hey @drselump14, Does mathieuprog/polymorphic_embed#96 fix this issue? |
It does make it slightly easier to work with, but is not the best "typing" you could get. Ideally we would look at all possible structs and compose the type that way, but as mentioned this should be maybe on a plug-in based way. This however is slight better. Thanks for doing that |
Agree that a composite type would be way better. In the anticipation of the first-class typing I'm starting to slowly care less about type specs though. :D Of course, production-ready typing for structs (and ubiquitous support in core libs and most dependencies) is probably not that close, but they make it clear that type specs will be phased out. |
Yeah, to be honest, me too. I don't want to make any big changes/moves as we wait for that to become a reality. Maybe at that time it can make sense for ecto to automatically generate the types itself or something like that. Best we can do is wait. In the meantime we can maybe make this library help as much as possible. |
Hi, I'd also like to use TypedEctoSchema together with PolymorphicEmbed. I would already be happy if I could simply write defmodule Example1 do
use TypedEctoSchema
import PolymorphicEmbed
typed_schema "todos" do
field(:content, :string)
field(:title, :string)
polymorphic_embeds_one(:form,
types: [
product_form: Todos.ProductForm,
order_form: Todos.OrderForm
],
on_type_not_found: :raise,
on_replace: :update
) :: Todos.ProductForm | Todos.OrderForm
polymorphic_embeds_many(:children,
types: [
text_todo: Todos.TextTodo,
visual_todo: Todos.VisualTodo
],
on_type_not_found: :raise,
on_replace: :delete
) :: [Todos.TextTodo | Todos.VisualTodo]
end
end Yes, it would definitely be better if the Polymorphic embedding type could be inferred, but this solution would at least allow me to continue using PolymorphicEmbed's DSL methods, instead of having to desugar them as @bamorim so expertly and extensively describes. While I'm not familar with TypedEctoSchema's codebase – I did browse through the source code a bit, but I literally just discovered this library today – it seems that allowing What do you think of this idea? And how simple/hard do you think it would be to implement that? Note: @bamorim I was following your field(:form, {:array, PolymorphicEmbed},
types: [
product_form: Todos.ProductForm
],
on_type_not_found: :raise,
on_replace: :update,
default: [],
array?: true
) :: [map()] Thanks a lot for your extensive analysis and workarounds. Without it, I would have found this library unusable in combination with PolymorphicEmbed. |
I started to get warnings in VSCode about my custom Ecto type field not having type "t": This workaround didn't help btw field(:myfield, CustomField, null: false) :: term() I can implement the |
That seems weird. Can you maybe give more details on that? |
Sorry, I've already removed typed_ecto_schema from the project |
Thank you for the great lib! With more or less recent changes in polymorphic embeds it's not possible to easily use |
Honestly, we can probably just make it work seamlessly with some well known libraries for now. I think it will make things easier for people using. We might eventually want to switch to a plug-in based approach but if we can make it work with PolymorphicEmbed it might be good enough. Unfortunately I don't have the time / mental capacity to do that right now but PRs are welcome. |
Hi guys, thanks for the fantastic library. It rocks!
Recently I'm struggling with
{:type_not_found, {PolymorphicEmbed, "t", "PolymorphicEmbed.t()"}
error when using polymorphic_embed library.The schema looks like this.
Not sure If I can redefine the external module with Elixir, so does anyone know
what's the best practice to solve this issue?
Any help would be appreciated.
The text was updated successfully, but these errors were encountered: