Search code examples
elixirgraphqlphoenix-frameworkectoabsinthe

Ecto looks for field_id instead of field


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 ?


Solution

  • 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