如何在 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-rubygraphql-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

连接支持一些开箱即用的参数,您可以在连接查询中使用firstlastbeforeafter

query 
  posts(first: 5) 
    edges 
      node 
        name
      
    
  

所有这些都记录在 Relay documentation 中,因此请务必阅读它以及 graphql-ruby 文档。

【讨论】:

以上是关于如何在 Rails 中设置 GraphQL Relay API的主要内容,如果未能解决你的问题,请参考以下文章

如何在graphql查询中设置loading true。?

如何在graphql突变中设置多对多关系?

如何在 springboot graphql 应用程序中设置基本 url

GraphQL:我需要在我的项目中设置啥?

Rails:如何在 ActiveRecord 中设置默认值?

Rails + Cucumber/Capybara:如何在测试中设置/检索 cookie?