Cracin
Cracin

Reputation: 523

Rails + Graphql - Failed to implement Game.id

I'm trying to implement a query type that can search by name of the record instead of id. Here's its definition in query_type.rb.

# Get game by name
field :game_by_name, Types::GameType, null: false do
  argument :name, String, required: true
end

def game_by_name(name:)
  Game.where(name: name) //find a game using the name attribute
end

But when I run:

query {
  gameByName(name: "League of Legends") {
    id
    name
  }
}

I get the following error.

Failed to implement Game.id, tried:\n\n        
- `Types::GameType#id`, which did not exist\n        
- `Game::ActiveRecord_Relation#id`, which did not exist\n        
- Looking up hash key `:id` or `\"id\"` on `#<Game::ActiveRecord_Relation:0x00007f5644442888>`, but it wasn't a Hash\n\n        
To implement this field, define one of the methods above (and check for typos)\n

This is odd because the following query type works perfectly.

# Get game by ID
field :game_by_id, Types::GameType, null: false do
  argument :id, ID, required: true
end

def game_by_id(id:)
  Game.find(id)
end

Here's game_type.rb:

module Types
  class GameType < Types::BaseObject
    field :id, ID, null: false
    field :name, String, null: false
  end
end

How do I go about fixing this? Thank you!

Upvotes: 7

Views: 4368

Answers (1)

shrunken_head
shrunken_head

Reputation: 217

I stumbled upon this, chasing a similar error. Not sure if you solved it or not, but I believe the issue is in the query type definition.

You're telling it to return a type of Types::GameType, but the Active Record query returns an Active Record Relation, which is a collection. So, graphql is expecting a single instance of Game, but is instead receiving a collection. Graphql is then trying to map the returned value from the query to the type definition, but is unable to. The best hint is from this line:

Looking up hash key `:id` or `\"id\"` on `#<Game::ActiveRecord_Relation:0x00007f5644442888>`, but it wasn't a Hash..

Graphql is trying to assign :id to the ActiveRecord_Relation and it can't do it.

Two paths forward, depending on how you want the API to behave. Do you want it to return 1 record or many?

Wrapping the Types::GameType within brackets will tell graphql it's a collection and to iterate over the records

# Get game by name
field :game_by_name, [Types::GameType], null: false do
  argument :name, String, required: true
end

def game_by_name(name:)
  Game.where(name: name) //find a game using the name attribute
end

or have Active Record return just 1 record, something like...

# Get game by name
field :game_by_name, Types::GameType, null: false do
  argument :name, String, required: true
end

def game_by_name(name:)
  Game.where(name: name).limit(1).first //find a game using the name attribute
end

I know this is months old, but just putting it out there for anyone else who stumbles upon this question, like I did!

Upvotes: 13

Related Questions