Association not found on preloads

Hello,

I need to preload an association on a get_by function, everything seems good but in the response it tell me there is no association

Here’s the concerned code :

Schema of the association :

  schema "users_cryptos" do
    belongs_to :user, Accounts.User
    belongs_to :crypto, Currencies.Crypto

    timestamps()
  end

  @doc false
  def changeset(user_crypto, attrs) do
    user_crypto
    |> cast(attrs, [:user_id, :crypto_id])
    |> validate_required([:user_id, :crypto_id])
    |> unique_constraint(:unique_subs, name: :subs_index)
  end

Controller calling the function :

  def index_by_user(conn, %{"user_id" => user_id}) do
    preloads = [:cryptos, :users]
    user_cryptos = Accounts.get_user_crypto_from_user!(user_id, preloads)
    render(conn, "index.json", users_cryptos: user_cryptos)
  end

Function in the context :

  def get_user_crypto_from_user!(user_id, preloads) do
    from(uc in UserCrypto, where: uc.user_id == ^user_id)
    |> Repo.all
    |> Repo.preload(preloads)
  end

If anyone sees the problem please take meout of Elixir preloads :')

The names passed to preload should match the names of the associations you want to preload.

In your case, that would mean passing preloads = [:crypto, :user] (no s) to get_user_crypto_from_user!

2 Likes

Thanks, i saw this just after your message…

Now it gives me a less understandable error, only in the console. I’ll take some time to get where’s the problem

[error] Task #PID<0.796.0> started from #PID<0.793.0> terminating
** (Protocol.UndefinedError) protocol Ecto.Queryable not implemented for Accounts.User of type Atom, the given module does not exist. This protocol is implemented for the following type(s): Atom, Ecto.Query, Tuple, Ecto.SubQuery, BitString
    (ecto 3.9.2) lib/ecto/queryable.ex:40: Ecto.Queryable.Atom.to_query/1
    (ecto 3.9.2) lib/ecto/query/builder/from.ex:145: Ecto.Query.Builder.From.apply/5
    (ecto 3.9.2) lib/ecto/association.ex:1041: Ecto.Association.BelongsTo.assoc_query/3
    (ecto 3.9.2) lib/ecto/repo/preloader.ex:244: Ecto.Repo.Preloader.fetch_query/8
    (elixir 1.12.2) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (elixir 1.12.2) lib/task/supervised.ex:35: Task.Supervised.reply/5
    (stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: &:erlang.apply/2
    Args: [#Function<8.13453492/1 in Ecto.Repo.Preloader.maybe_pmap/3>, [#Function<20.13453492/1 in Ecto.Repo.Preloader.prepare_queries/6>]]
[error] Task #PID<0.797.0> started from #PID<0.793.0> terminating
** (Protocol.UndefinedError) protocol Ecto.Queryable not implemented for Currencies.Crypto of type Atom, the given module does not exist. This protocol is implemented for the following type(s): Atom, Ecto.Query, Tuple, Ecto.SubQuery, BitString
    (ecto 3.9.2) lib/ecto/queryable.ex:40: Ecto.Queryable.Atom.to_query/1
    (ecto 3.9.2) lib/ecto/query/builder/from.ex:145: Ecto.Query.Builder.From.apply/5
    (ecto 3.9.2) lib/ecto/association.ex:1041: Ecto.Association.BelongsTo.assoc_query/3
    (ecto 3.9.2) lib/ecto/repo/preloader.ex:244: Ecto.Repo.Preloader.fetch_query/8
    (elixir 1.12.2) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (elixir 1.12.2) lib/task/supervised.ex:35: Task.Supervised.reply/5
    (stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: &:erlang.apply/2
    Args: [#Function<8.13453492/1 in Ecto.Repo.Preloader.maybe_pmap/3>, [#Function<20.13453492/1 in Ecto.Repo.Preloader.prepare_queries/6>]]
[error] Ranch protocol #PID<0.793.0> of listener CryptoApiWeb.Endpoint.HTTP (connection #PID<0.782.0>, stream id 3) terminated
an exception was raised:
    ** (Protocol.UndefinedError) protocol Ecto.Queryable not implemented for Accounts.User of type Atom, the given module does not exist. This protocol is implemented for the following type(s): Atom, Ecto.Query, Tuple, Ecto.SubQuery, BitString
        (ecto 3.9.2) lib/ecto/queryable.ex:40: Ecto.Queryable.Atom.to_query/1
        (ecto 3.9.2) lib/ecto/query/builder/from.ex:145: Ecto.Query.Builder.From.apply/5
        (ecto 3.9.2) lib/ecto/association.ex:1041: Ecto.Association.BelongsTo.assoc_query/3
        (ecto 3.9.2) lib/ecto/repo/preloader.ex:244: Ecto.Repo.Preloader.fetch_query/8
        (elixir 1.12.2) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
        (elixir 1.12.2) lib/task/supervised.ex:35: Task.Supervised.reply/5
        (stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3

Check your user_crypto.ex file - the messages suggest that Accounts.User and Currencies.Crypto aren’t being aliased correctly.

In a typical Phoenix app, they would have full names like SomeApplicationName.Accounts.User and SomeApplicationName.Currencies.Crypto and then user_crypto.ex would include:

alias SomeApplicationName.Accounts
alias SomeApplicationName.Currencies

inside the defmodule block.

1 Like

It did work indeed, i don’t know how anything worked without alias before that, thanks a lot i can finally generalize that to all my preloads problems :')