如何在 Rails 中设置 GraphQL Relay API
Posted
技术标签:
【中文标题】如何在 Rails 中设置 GraphQL Relay API【英文标题】:How to setup a GraphQL Relay API in Rails 【发布时间】:2017-06-30 01:31:03 【问题描述】:我正试图围绕 GraphQL/Relay 展开思考,但我发现很难开始了解如何使用 Ruby on Rails 正确设置符合 Relay 的 GraphQL API。
我找到了多个关于如何做到这一点的教程:
https://medium.com/react-weekly/relay-facebook-on-rails-8b4af2057152#.gd8p6tbwi
https://medium.com/@gauravtiwari/graphql-and-relay-on-rails-getting-started-955a49d251de#.m05xjvi82
但它们都引用了一个 graphql-relay
的 gem,目前似乎不可用:https://github.com/rmosolgo/graphql-relay-ruby
grahql-ruby
gem 在文档中有一个特定于relay 的部分,但我发现很难理解需要什么来设置它以供 Relay 客户端使用。
在 Rails 中为 Relay 客户端实现 GraphQL API 需要什么?
【问题讨论】:
【参考方案1】:你试过安装吗?
vagrant$ bundle install
Fetching gem metadata from https://rubygems.org/............
Fetching version metadata from https://rubygems.org/...
Fetching dependency metadata from https://rubygems.org/..
Resolving dependencies...
Installing graphql 0.19.4
Using bundler 1.11.2
Installing graphql-relay 0.12.0
Bundle complete! 1 Gemfile dependency, 3 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
在 Gemfile 中:
gem 'graphql-relay'
【讨论】:
是的,它确实有效,但它使用的是旧版本的graphql
。我发现graphql-ruby
和graphql-relay
被合并了。我正在尝试更轻松地构建 api 以更好地回答这个问题,因为开始使用它绝对是一种痛苦【参考方案2】:
我只想把我的发现留在这里,以供将来遇到此问题并希望指出更好方向的任何人使用。
首先,graphql-ruby
gem 包含实现 Relay 兼容的 GraphQL API 所需的一切。 in 包括之前在 graphql-relay
gem 中的所有内容。
您需要在 Schema 中提供 2 个东西以使 Relay 重新获取功能正常工作,一个 id_from_object
方法将您域中的对象转换为全局 id,还有一个 object_from_id
方法将将全局 id 解码为应用程序中的对象:
ApplicationSchema = GraphQL::Schema.define do
/* Create IDs by joining the type name & ID, then base64-encoding it */
id_from_object ->(object, type_definition, query_ctx)
GraphQL::Schema::UniqueWithinType.encode(type_definition.name, object.id)
object_from_id ->(id, query_ctx)
type_name, object_id = GraphQL::Schema::UniqueWithinType.decode(id)
# Now, based on `type_name` and `id`
# find an object in your application
# This will give the user access to all records in your db
# so you might want to restrict this properly
Object.const_get(type_name).find(object_id)
end
此外,您的所有类型都应实现 ruby gem 提供的 NodeInterface
,并公开 global_id_field
而不是 ID 类型:
PostType = GraphQL::ObjectType.define do
name "Post"
# Implements the "Node" interface for Relay
interfaces [GraphQL::Relay::Node.interface]
# exposes the global id
global_id_field :id
field :name, types.String
end
这将允许 Relay 像这样重新获取数据:
query
node(id: "RmFjdGlvbjox")
id
... on Post
name
Relay 还使用 babel-relay-plugin
,它需要生成 schema.json 并可供客户端使用,如果您正在构建一个没有视图呈现的隔离 API,则可以让客户端获取架构而不是在服务器中完成这项工作,apollo-codegen 之类的东西可以工作。但是,如果您正在构建一个 rails 应用程序并且需要在同一个应用程序中使用架构,那么您可以运行自省查询并使用 rake 任务将结果保存到 json 文件中:
Schema.execute GraphQL::Introspection::INTROSPECTION_QUERY
最后,您需要了解 Relay 表达了与连接的一对多关系:
PostType = GraphQL::ObjectType.define do
# default connection
# obj.comments by default
connection :comments, CommentType.connection_type
# custom connection
connection :featured_comments, CommentType.connection_type do
resolve ->(post, args, ctx)
comments = post.comments.featured
if args[:since]
comments = comments.where("created_at >= ?", since)
end
comments
end
end
连接支持一些开箱即用的参数,您可以在连接查询中使用first
、last
、before
和after
:
query
posts(first: 5)
edges
node
name
所有这些都记录在 Relay documentation 中,因此请务必阅读它以及 graphql-ruby 文档。
【讨论】:
以上是关于如何在 Rails 中设置 GraphQL Relay API的主要内容,如果未能解决你的问题,请参考以下文章
如何在 springboot graphql 应用程序中设置基本 url