polymorphic_embed icon indicating copy to clipboard operation
polymorphic_embed copied to clipboard

Don't create compile-time dependencies to embedded schemas

Open crbelaus opened this issue 1 year ago • 0 comments

When using polymorphic_embeds_one or polymorphic_embeds_many we create compile-time dependencies from the parent schema to the embedded schemas.

For example, let's say we have the following code:

# lib/article.ex
defmodule Article do
  use Ecto.Schema

  import PolymorphicEmbed

  embedded_schema do
    polymorphic_embeds_many :thing,
      types: [comment: Comment, reaction: Reaction],
      on_replace: :delete
  end
end

# lib/comment.ex
defmodule Comment do
  use Ecto.Schema

  embedded_schema do
    field :content, :string
  end
end

# lib/reaction.ex
defmodule Reaction do
  use Ecto.Schema

  embedded_schema do
    field :content, :string
  end
end

This provides the following output. As we can see, the Article schema has a compile-time dependency on the Comment and Reaction schemas:

mix xref graph --source lib/article.ex --label compile

lib/article.ex
├── lib/comment.ex (compile)
├── lib/polymorphic_embed.ex (compile)
└── lib/reaction.ex (compile)

Ecto had this same issue early on with associations. In particular with embeds_one and embeds_many. They solved it by expanding the aliases and disabling the lexical tracker for associated schemas as shown in elixir-ecto/ecto#1670.

This pull request applies the same solution. This is safe since we don't call any functions in the associated schemas. The result is that running the previous command shows that there are no compile-time dependencies anymore.

mix xref graph --source lib/article.ex --label compile

lib/article.ex
└── lib/polymorphic_embed.ex (compile)

Closes #85

crbelaus avatar Jul 25 '23 14:07 crbelaus