Ecto preload nested

Hi Folks,
First time posting, so, sorry if in the wrong category. I’m new to elixir and I’m trying to learn by making a small system to manage some customers. I researched but can’t understand how a nested preload with ecto works.

I have a basic structure like below:

schema "users" do
    field :name, :string
    field :email, :string
    #[...] more fields hidden here
    belongs_to :tenants, MeuClube.Tenants.Tenant

  end

and I’m trying to change the verify_session_token_query method generated by Phoenix authentication generator. I

from token in by_token_and_context_query(token, "session"),
        join: user in assoc(token, :user),
        join: t in assoc(user, :tenants),
        where: token.inserted_at > ago(@session_validity_in_days, "day"),
        preload: [user: {tenants: t}],
        select: user

With the preload above I get the following: syntax error before: tenants. Changing to preload: [user: {user, tenants: t}], I get a different error the binding used in 'from' must be selected in 'select' when using 'preload' in query:

I think there should always be keyword lists. So try replace tuple syntax (curly) with brackets

2 Likes

That’s an invalid Elixir syntax. Replace with:

preload: [user: [tenants: t]]
2 Likes

Hi Folks,

that’s a weird syntax to me hahahaha. Changing to preload: [user: [tenants: t]], I got the following

(Ecto.Query.CompileError) cannot preload join association :tenantswith bindingt because parent preload is not a join association.

I understand that the VM thinks that the User isn’t a join association, right?

I read somewhere that the preload should go deep in the association tree, so I also tried to put the token into the preload

[token: [user: [tenants: t]]]

But I got the same error. Will keep trying to find an answer on why that join isn’t a join :slight_smile: . Ty for the help till now folks.

try

[user: :tenants]

Nope :slight_smile:

the binding used in `from` must be selected in `select` when using `preload` in query:

For now, I’ll just preload using the |> Repo.preload([:tenants]) it’ll work, not the way I think its faster, but will work