Skip to content

Commit

Permalink
Disable lexical tracker for embedded modules
Browse files Browse the repository at this point in the history
When using `polymorphic_embeds_one` or `polymorphic_embeds_many` we
create compile-time dependencies from the parent schema to the embedded
schemas.

This change expands the embedded schema module names and removes the
lexical tracker to avoid creating this compile-time dependencies. This is
safe to do since in this place we are not calling any functions on the
association modules.

This uses the same approach that was used in Ecto's `embeds_one` and
`embeds_many` associations: elixir-ecto/ecto#1670
  • Loading branch information
crbelaus committed Jul 25, 2023
1 parent 78e51d9 commit 48f3230
Showing 1 changed file with 27 additions and 1 deletion.
28 changes: 27 additions & 1 deletion lib/polymorphic_embed.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,45 @@ defmodule PolymorphicEmbed do
use Ecto.ParameterizedType

defmacro polymorphic_embeds_one(field_name, opts) do
opts = Keyword.update!(opts, :types, &expand_alias(&1, __CALLER__))

quote do
field(unquote(field_name), PolymorphicEmbed, unquote(opts))
end
end

defmacro polymorphic_embeds_many(field_name, opts) do
opts = Keyword.merge(opts, default: [])
opts =
opts
|> Keyword.put_new(:default, [])
|> Keyword.update!(:types, &expand_alias(&1, __CALLER__))

quote do
field(unquote(field_name), {:array, PolymorphicEmbed}, unquote(opts))
end
end

# Expand module aliases to avoid creating compile-time dependencies between the
# parent schema that uses `polymorphic_embeds_one` or `polymorphic_embeds_many`
# and the embedded schemas.
defp expand_alias(types, env) do
Enum.map(types, fn
{type_name, type_opts} when is_list(type_opts) ->
{type_name, Keyword.update!(type_opts, :module, &do_expand_alias(&1, env))}

{type_name, module} ->
{type_name, do_expand_alias(module, env)}
end)
end

defp do_expand_alias({:__aliases__, _, _} = ast, env) do
Macro.expand(ast, %{env | lexical_tracker: nil})
end

defp do_expand_alias(ast, _env) do
ast
end

@impl true
def type(_params), do: :map

Expand Down

0 comments on commit 48f3230

Please sign in to comment.