I am trying to setup a Phoenix API with GraphQL.
I have a Team
table and a Game
Table in my DB like this:
schema "teams" do
field :name, :string
has_many :games, LvdnApi.Fixtures.Game
timestamps()
end
schema "games" do
field :away_team_score, :integer
field :competition, :string
field :game_datetime, :utc_datetime
field :home_team_score, :integer
field :round, :string
belongs_to :home_team, LvdnApi.Fixtures.Team
belongs_to :away_team, LvdnApi.Fixtures.Team
timestamps()
end
@doc false
def changeset(game, attrs) do
game
|> cast(attrs, [:home_team_score, :away_team_score, :competition, :round, :game_datetime, :home_team, :away_team])
|> validate_required([:competition, :round, :game_datetime, :home_team, :away_team])
|> assoc_constraint(:home_team)
|> assoc_constraint(:away_team)
end
And here are my objects in my Absinthe Schema:
object :team do
field :id, non_null(:id)
field :name, non_null(:string)
end
object :game do
field :id, non_null(:id)
field :home_team, :team, resolve: assoc(:home_team)
field :away_team, :team, resolve: assoc(:away_team)
field :home_team_score, :integer
field :away_team_score, :integer
field :competition, non_null(:string)
field :round, non_null(:string)
field :game_datetime, non_null(:datetime)
end
Let's say I want to perform a simple GraphQL query like so:
{
allGames{
id
homeTeam {
id
}
}
}
I get the following error:
[error] #PID<0.517.0> running LvdnApiWeb.Endpoint (connection #PID<0.516.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: POST /api/v1/graphiql
** (exit) an exception was raised:
** (Postgrex.Error) ERROR 42703 (undefined_column) column g0.home_team_id does not exist
query: SELECT g0."id", g0."away_team_score", g0."competition", g0."game_datetime", g0."home_team_score", g0."round", g0."home_team_id", g0."away_team_id", g0."inserted_at", g0."updated_at" FROM "games" AS g0
hint: Perhaps you meant to reference the column "g0.home_team".
(ecto_sql) lib/ecto/adapters/sql.ex:605: Ecto.Adapters.SQL.raise_sql_call_error/1
(ecto_sql) lib/ecto/adapters/sql.ex:538: Ecto.Adapters.SQL.execute/5
(ecto) lib/ecto/repo/queryable.ex:147: Ecto.Repo.Queryable.execute/4
(ecto) lib/ecto/repo/queryable.ex:18: Ecto.Repo.Queryable.all/3
(lvdn_api) lib/lvdn_api_web/resolvers/fixtures_resolvers.ex:17: LvdnApiWeb.FixturesResolver.all_games/3
(absinthe) lib/absinthe/resolution.ex:209: Absinthe.Resolution.call/2
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:209: Absinthe.Phase.Document.Execution.Resolution.reduce_resolution/1
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:168: Absinthe.Phase.Document.Execution.Resolution.do_resolve_field/4
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:153: Absinthe.Phase.Document.Execution.Resolution.do_resolve_fields/6
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:72: Absinthe.Phase.Document.Execution.Resolution.walk_result/5
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:53: Absinthe.Phase.Document.Execution.Resolution.perform_resolution/3
(absinthe) lib/absinthe/phase/document/execution/resolution.ex:24: Absinthe.Phase.Document.Execution.Resolution.resolve_current/3
(absinthe) lib/absinthe/pipeline.ex:274: Absinthe.Pipeline.run_phase/3
(absinthe_plug) lib/absinthe/plug.ex:421: Absinthe.Plug.run_query/4
(absinthe_plug) lib/absinthe/plug.ex:247: Absinthe.Plug.call/2
(phoenix) lib/phoenix/router/route.ex:39: Phoenix.Router.Route.call/2
(phoenix) lib/phoenix/router.ex:275: Phoenix.Router.__call__/1
(lvdn_api) lib/lvdn_api_web/endpoint.ex:1: LvdnApiWeb.Endpoint.plug_builder_call/2
(lvdn_api) lib/plug/debugger.ex:122: LvdnApiWeb.Endpoint."call (overridable 3)"/2
(lvdn_api) lib/lvdn_api_web/endpoint.ex:1: LvdnApiWeb.Endpoint.call/2
As you can see, Ecto looks for home_team_id
whereas the field in the Game
table is called home_team
.
What can I change so that it looks for the right field name ?
I just found out the problem came from the migration which I did not post here (sorry about that !)
I had :
def change do
create table(:games) do
add :home_team_score, :integer
add :away_team_score, :integer
add :competition, :string
add :round, :string
add :game_datetime, :utc_datetime
add :home_team, references(:teams, on_delete: :nothing)
add :away_team, references(:teams, on_delete: :nothing)
timestamps()
end
create index(:games, [:home_team])
create index(:games, [:away_team])
end
And the right code is :
def change do
create table(:games) do
add :home_team_score, :integer
add :away_team_score, :integer
add :competition, :string
add :round, :string
add :game_datetime, :utc_datetime
add :home_team_id, references(:teams, on_delete: :nothing)
add :away_team_id, references(:teams, on_delete: :nothing)
timestamps()
end
create index(:games, [:home_team_id])
create index(:games, [:away_team_id])
end