bamorim / typed_ecto_schema

A library to define Ecto schemas with typespecs without all the boilerplate code.
https://hexdocs.pm/typed_ecto_schema
Apache License 2.0
267 stars 18 forks source link

Fields still cause compile-time dependencies #38

Open axelson opened 1 year ago

axelson commented 1 year ago

Modules referenced as fields still create compile-time dependencies. e.g. this is an issue:

defmodule Person do
  use TypedEctoSchema

  typed_schema "people" do
    field(:country, Country, enforce: true, null: false)
  end
end

While this is not an issue:

defmodule Person do
  use TypedEctoSchema

  typed_schema "people" do
    belongs_to(:company, Company)
  end
end

I've created a simple phoenix project that serves as a reproduction of this issue: https://github.com/axelson/typed_struct_compile_repro

In it I expect this command to not show any compile-time dependencies, but instead it shows one compile-time dependency:

mix xref graph --source lib/typed_demo/person.ex
lib/typed_demo/person.ex
├── lib/typed_demo/company.ex
└── lib/typed_demo/country.ex (compile)

I believe this is a subset that was not fixed with https://github.com/bamorim/typed_ecto_schema/pull/18 (original issue filed as https://github.com/bamorim/typed_ecto_schema/issues/6)

dvic commented 1 year ago

The second example is using a belongs_to while the first one is using field :)

If you change it to belongs_to in the first example, you'll see that the compile-time dependency disappears :) In case Country was an Ecto.Type, then you would have to use field, but that compile-time dependency is actually introduced by Ecto, so there's not much we can do.

axelson commented 1 month ago

Guess I never responded to this 🫣 What you say makes a lot of sense, and we definitely can't remove a compile-dep that Ecto is adding.

Although what brings me here today is I found another case where typed_ecto_schema adds a compile-dep where Ecto doesn't have it, the join_through of a many_to_many:

defmodule Many.User do
  import TypedEctoSchema

  typed_schema "users" do
    field :name, :string
    field :email, :string

    many_to_many :book_reviews, Many.BookReview,
      join_through: Many.Book,
      unique: true,
      on_replace: :delete
  end
end

I tried spelunking through the code but I couldn't find anything that stood out to me.

Edit: I've created a reproduction repo for this here: https://github.com/axelson/typed_ecto_schema_repro