Rails + Graphql - 无法实现 Game.id

Cra*_*cin 7 ruby-on-rails graphql

我正在尝试实现一种可以按记录名称而不是 ID 进行搜索的查询类型。这是它在 中的定义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
Run Code Online (Sandbox Code Playgroud)

但是当我跑步时:

query {
  gameByName(name: "League of Legends") {
    id
    name
  }
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误。

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
Run Code Online (Sandbox Code Playgroud)

这很奇怪,因为以下查询类型可以完美运行。

# 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
Run Code Online (Sandbox Code Playgroud)

这是game_type.rb

module Types
  class GameType < Types::BaseObject
    field :id, ID, null: false
    field :name, String, null: false
  end
end
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?谢谢你!

shr*_*ead 13

我偶然发现了这一点,追寻类似的错误。不确定您是否解决了这个问题,但我相信问题出在查询类型定义中。

您告诉它返回 类型Types::GameType,但 Active Record 查询返回 Active Record Relation,它是一个集合。因此,graphql 期望的是 的单个实例Game,但接收的是一个集合。然后 Graphql 尝试将查询返回的值映射到类型定义,但无法做到。最好的提示来自这一行:

Looking up hash key `:id` or `\"id\"` on `#<Game::ActiveRecord_Relation:0x00007f5644442888>`, but it wasn't a Hash..
Run Code Online (Sandbox Code Playgroud)

Graphql 正在尝试分配:idActiveRecord_Relation,但它无法执行此操作。

两种前进路径,具体取决于您希望 API 的行为方式。您希望它返回 1 条记录还是多条记录?

将括号括起来Types::GameType将告诉 graphql 这是一个集合并迭代记录

# 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
Run Code Online (Sandbox Code Playgroud)

或者让 Active Record 仅返回 1 条记录,例如...

# 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
Run Code Online (Sandbox Code Playgroud)

我知道这已经有几个月了,但只是把它放在那里给其他像我一样偶然发现这个问题的人!