1

I've added a many to many association to a couple of my models and it seems to work fine in isolation--meaning w/o the GraphQL schema declarations. Here is the code for one of my models:

  use Ecto.Schema
  import Ecto.Changeset

  alias Trader.Collect.Card

  schema "users" do
    field(:email, :string)
    field(:first_name, :string)
    field(:last_name, :string)
    field(:password, :string)
    field(:username, :string)

    many_to_many(:cards, Card, join_through: "user_cards")

    timestamps()
  end

  @doc false
  def changeset(user, attrs) do
    user
    |> cast(attrs, [:first_name, :last_name, :email, :username, :password])
    |> validate_required([:first_name, :last_name, :email, :username, :password])
  end
end

And here is the GraphQL type declaration:

defmodule TraderWeb.Schema.Types.User do
  use Absinthe.Schema.Notation

  @desc "User model representation"
  object :user do
    field(:id, non_null(:id))
    field(:first_name, non_null(:string))
    field(:last_name, non_null(:string))
    field(:username, non_null(:string))
    field(:email, non_null(:string))
    field(:password, non_null(:string))
    # field(:cards, list_of(:card), resolve: assoc(:cards))
  end
end

This is the top level schema definition for the Absinthe/GraphQL part:

defmodule TraderWeb.Schema.Schema do
  use Absinthe.Schema

  import_types(Absinthe.Type.Custom)

  # Import Types individually here
  import_types(TraderWeb.Schema.Types.{
    User,
    Card,
    CardSet
  })

  # import queries here
  import_types(TraderWeb.Schema.Queries.{
    User,
    Card,
    CardSet
  })

  query do
    import_fields(:user_queries)
    import_fields(:card_queries)
    import_fields(:card_set_queries)
  end
end

Please note the cards field is commented out in the Type. Everything works fine in this case, however, if I uncomment that cards field, I get the following error:

== Compilation error in file lib/trader_web/schema/types/user.ex ==
** (CompileError) lib/trader_web/schema/types/user.ex:12: undefined function assoc/1
    (elixir) src/elixir_locals.erl:108: :elixir_locals."-ensure_no_undefined_local/3-lc$^0/1-0-"/2
    (elixir) src/elixir_locals.erl:108: anonymous fn/3 in :elixir_locals.ensure_no_undefined_local/3
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (elixir) lib/kernel/parallel_compiler.ex:229: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7

I've googled this issue pretty aggressively and can't find anything for this. It's unclear where that assoc function even lives--is it an ecto thing? or an absinthe-ecto thing? I also found sample code somewhere using dataloader but I couldn't get that working at all.

I appreciate any thoughts and ideas you all have! thanks

jaydel
  • 14,389
  • 14
  • 62
  • 98

1 Answers1

1

You will either need the (deprecated) Absinthe.Ecto package, or work with the new Dataloader. There is a section in the documentation for Absinthe on Ecto best practices, which describes the new syntax for using dataloader https://hexdocs.pm/absinthe/ecto.html#dataloader. As that also requires additions to your context, it would be too much to add the complete setup here, but the docs are pretty good.

Julia Will
  • 616
  • 3
  • 8