如何设置RubyonRailsGraphQLAPI

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Free Press 来接受捐赠。

介绍

GraphQL 是一种用于 API 的强类型查询语言和用于使用现有数据执行这些查询的服务器端运行时。 GraphQL 通过让客户端能够指定查询中所需的确切数据,允许客户端在单个请求中从服务器获取多个资源。 这消除了对多个 API 调用的需要。 GraphQL 独立于语言和数据库,因此可以在几乎所有编程语言以及任何选择的数据库中实现。

在本教程中,您将构建一个基于 GraphQL 的 Ruby on Rails API 来做笔记。 完成后,您将能够使用 GraphQL 从 API 创建和查看笔记。

如果您想查看本教程的代码,请查看 DigitalOcean 社区 GitHub 上本教程的 配套存储库

先决条件

要学习本教程,您需要:

  • 安装在开发机器上的 Ruby 编程语言和 Ruby on Rails 框架。 本教程在 Ruby 的 2.6.3 版本和 Rails 的 6.0.2.1 版本上进行了测试,因此请确保在安装过程中指定这些版本。 按照以下教程之一安装 Ruby 和 Rails: 如何在 Ubuntu 18.04 上使用 rbenv 安装 Ruby on Rails 如何在 CentOS 7 上使用 rbenv 安装 Ruby on Rails。 如何在 macOS 上使用 rbenv 安装 Ruby on Rails。
  • 安装了 PostgreSQL。 要遵循本教程,请使用 PostgreSQL 版本 11.2。 按照以下教程之一的步骤 1 和 2 安装 PostgreSQL: 如何在 Ubuntu 18.04 上将 PostgreSQL 与您的 Ruby on Rails 应用程序一起使用 如何在 macOS 上将 PostgreSQL 与您的 Ruby on Rails 应用程序一起使用。 要在不同的 Linux 发行版或其他操作系统上开发此应用程序,请访问官方 PostgreSQL 下载页面。 有关如何使用 PostgreSQL 的更多信息,请访问如何安装和使用 PostgreSQL。

第 1 步 — 设置新的 Rails API 应用程序

在这一步中,您将设置一个新的 Rails API 应用程序并将其连接到 PostgreSQL 数据库。 这将作为笔记 API 的基础。

Rails 提供的命令可以让开发人员更快地构建现代 Web 应用程序。 这些命令可以执行从创建新 Rails 应用程序到生成应用程序开发所需文件的各种操作。 有关这些命令的完整列表及其作用,请在终端窗口中运行以下命令:

rails -h

此命令生成可用于设置应用程序参数的广泛选项列表。 列出的命令之一是 new 命令,它接受 APP_PATH 并在指定路径创建一个新的 Rails 应用程序。

使用 new 生成器创建一个新的 Rails 应用程序。 在终端窗口中运行以下命令:

rails new rails_graphql -d=postgresql -T --api

这将在名为 rails_graphql 的目录中创建一个新的 Rails 应用程序并安装所需的依赖项。 让我们回顾一下与 new 命令相关的标志:

  • -d 标志使用指定的数据库预先配置应用程序。
  • -T 标志指示 Rails 不生成测试文件,因为您不会在本教程中编写测试。 如果您计划使用不同于 Rails 提供的测试框架,您也可以使用此标志。
  • --api 标志配置 Rails 应用程序,仅包含使用 Rails 构建 API 所需的文件。 它跳过配置浏览器应用程序所需的设置。

命令运行完成后,切换到新创建的 rails_graphql 目录,即应用程序的根目录:

cd rails_graphql

现在您已经成功设置了一个新的 Rails API 应用程序,您必须先将其连接到数据库,然后才能运行该应用程序。 Rails 提供了一个 config/database.yml 中的 database.yml 文件,其中包含用于将您的应用程序连接到不同开发环境的不同数据库的配置。 Rails 通过在应用程序名称后面附加一个下划线 (_) 和环境名称来指定不同开发环境的数据库名称。 您始终可以将任何环境数据库名称更改为您选择的任何名称。

注意: 你可以改变 config/database.yml 来选择你希望 Rails 用来创建数据库的 PostgreSQL 角色。 如果您创建了受密码保护的角色,请按照 How To Use PostgreSQL with Your Ruby on Rails Application on Ubuntu 18.04How To 的 Step 4 中的说明进行操作在 macOS 上将 PostgreSQL 与您的 Ruby on Rails 应用程序一起使用来配置您的角色。


Rails 包含用于创建和使用数据库的命令。 准备好数据库凭据后,在终端窗口中运行以下命令来创建数据库:

rails db:create

db:create 命令根据 config/database.yml 文件中提供的信息创建 developmenttest 数据库。 运行该命令会产生以下输出:

OutputCreated database 'rails_graphql_development'
Created database 'rails_graphql_test'

现在您的应用程序已成功连接到数据库,您可以测试该应用程序以确保其正常工作。 如果您在本地工作,请使用以下命令启动服务器:

bundle exec rails server

如果您在开发服务器上工作,您可以通过指定服务器应绑定到的 IP 地址来启动应用程序:

bundle exec rails server --binding=your_server_ip

:服务器监听端口3000。 如果您在开发服务器上工作,请确保您已在防火墙中打开端口 3000 以允许连接。


rails server 命令启动 Puma,一个用于 Ruby 的 Web 服务器,与 Rails 一起分发。 --binding=your_server_ip 命令将服务器绑定到您提供的任何 IP。

运行此命令后,您的命令提示符将替换为以下输出:

Output=> Booting Puma
=> Rails 6.0.2.1 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.1 (ruby 2.6.3-p62), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop

要运行您的应用程序,请在浏览器中导航至 localhost:3000http://your_server_ip:3000。 您将看到 Rails 默认的欢迎页面:

欢迎页面意味着您已经正确设置了 Rails 应用程序。

要停止服务器,请在运行服务器的终端窗口中按 CTRL+C

您已经成功地为笔记 API 设置了 Rails API 应用程序。 在下一步中,您将设置 Rails API 应用程序以接收和执行 GraphQL 查询。

第 2 步 — 为 Rails 设置 GraphQL

在这一步中,您将配置 Rails API 应用程序以使用 GraphQL。 您将在 Rails 中安装和设置 GraphQL 开发所需的必要 gem。

如前所述,GraphQL 与语言无关,并在许多编程语言中实现。 graphql-ruby gem 是 GraphQL 的 Ruby 实现。 GraphQL 还提供了一个名为 GraphiQL 的交互式浏览器内 IDE,用于运行 GraphQL 查询。 graphiql-rails gem 可帮助您将 GraphiQL 添加到您的开发环境中。

要安装这些依赖项,请使用 nano 或您喜欢的文本编辑器打开项目的 Gemfile 进行编辑:

nano Gemfile

graphqlgraphiql-rails gem 添加到您的 Gemfile。 您可以在任何地方添加 graphiql gem,但应在开发依赖项下添加 graphiql-rails gem:

~/rails_graphql/Gemfile

...
group :development do
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  gem 'graphiql-rails'
end

gem 'graphql', '1.9.18'
...

添加完 gem 后保存并关闭文件。

在终端窗口中,使用以下命令安装 gem:

bundle install

输出显示 gems 已安装。

graphql gem 提供生成器来创建各种文件。 要查看可用的生成器,请在终端窗口中运行以下命令:

rails generate

graphql: 为前缀的生成器是与 graphql gem 相关联的生成器。

您将使用 graphql:install 命令将 graphql-ruby 样板代码添加到应用程序并在您的开发环境中安装 GraphiQL。 样板代码将包含 graphql-ruby gem 使用 Rails 所需的所有文件和目录。

在您的终端窗口中,运行以下命令:

rails g graphql:install

此命令生成多个文件,包括位于 app/controllers/graphql_controller.rbgraphql_controller.rb 文件和位于 app/graphqlgraphql 目录,其中包含在 Rails 中开始使用 GraphQL 所需的文件. 它还在位于 config/routes.rb 的路由文件中添加了 /graphql HTTP POST 路由。 此路由映射到 app/controllers/graphql_controller.rb#execute 方法,该方法处理对 GraphQL 服务器的所有查询。

在您可以测试 GraphQL 端点之前,您需要将 GraphiQL 引擎安装到路由文件,以便您可以访问 GraphiQL 浏览器内的 IDE。 为此,打开位于 config/routes.rb 的路由文件:

nano ~/rails_graphql/config/routes.rb

将以下代码添加到文件中以在开发环境中挂载 GraphiQL 引擎:

~/rails_graphql/config/routes.rb

Rails.application.routes.draw do
  if Rails.env.development?
    mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "graphql#execute"
  end
  post "/graphql", to: "graphql#execute"
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

这会将 GraphiQL 引擎安装到 /graphiql 路径,并将所有查询定向到 graphql#execute 方法。

由于这是使用 --api 标志创建的 API 应用程序,因此它不希望在浏览器中呈现任何页面。 要使 GraphiQL 编辑器显示在浏览器中,您需要对应用程序的配置进行一些小的更改。

首先,打开位于 config/application.rbapplication.rb 文件:

nano ~/rails_graphql/config/application.rb

接下来,取消注释 require "sprockets/railtie" 行:

~/rails_graphql/config/application.rb

require_relative 'boot'

require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_mailbox/engine"
require "action_text/engine"
require "action_view/railtie"
require "action_cable/engine"
require "sprockets/railtie"
# require "rails/test_unit/railtie"

...

取消注释后保存并关闭文件。

现在在 app/assets 创建一个 config 目录:

mkdir -p app/assets/config

接下来,在新创建的config目录下创建一个manifest.js文件。 manifest.js 文件指定要编译并提供给浏览器的附加资产:

nano app/assets/config/manifest.js

将以下代码添加到文件中,告诉 Rails 预编译 graphiql/rails/application.cssgraphiql/rails/application.js 文件,以便 Rails 可以将它们提供给您的浏览器:

~/rails_graphql/app/assets/config/manifest.js

//= link graphiql/rails/application.css
//= link graphiql/rails/application.js

保存并关闭文件。

完成后,您可以测试 GraphQL 端点。 重新启动开发服务器,然后在浏览器中导航到 localhost:3000/graphiqlhttp://your_server_ip:3000/graphiql。 GraphiQL 查询编辑器显示在您的浏览器中:

GraphiQL IDE 的左侧接受 GraphQL 查询,右侧显示运行查询的结果。 GraphiQL 查询编辑器还具有由 GraphQL Schema 提供支持的语法高亮显示和预先输入提示。 这些一起帮助您进行有效的查询。

要尝试 Hello World 示例,请清除编辑器左窗格中的默认文本并键入以下查询:

query {
    testField
}

点击标题中的播放图标按钮,屏幕上会收到成功响应,如下图所示:

您已成功设置 Rails API 应用程序以使用 GraphQL 并测试您的 GraphQL 端点以确认它可以正常工作。 在下一步中,您将为您的应用程序创建 GraphQL 类型。

第 3 步 — 为应用程序创建类型

GraphQL 依赖于它的 Types 和 Schema 来验证和响应查询。 在此步骤中,您将创建笔记模型和笔记 API 中所需的 GraphQL 类型。

GraphQL 类型由 fieldsarguments 组成,它们反过来定义了可以出现在对该类型进行操作的任何 GraphQL 查询中的字段和参数。 这些类型构成了 GraphQL Schema。 GraphQL 定义了以下类型:

  • Query 和 Mutation 类型:这些是定义每个 GraphQL 查询入口点的特殊类型。 每个 GraphQL 服务都有一个 query 类型,可能有也可能没有 mutation 类型。
  • 对象类型:这些是 GraphQL 模式的基本组件。 这些代表您可以从 GraphQL 服务中获取的对象以及每个对象包含的字段。
  • 标量类型:这些是 GraphQL 开箱即用的默认类型。 它们包括 IntFloatStringBooleanID
  • 枚举类型:这些类型定义了一组特定的允许值。
  • 输入类型:这些类似于对象类型,唯一的区别是它们定义了可以作为参数传递给查询的对象。

还有其他类型,包括UnionListNon-NullInterface。 您可以在官方 GraphQL 文档 中找到可用的 GraphQL 类型列表。

对于此应用程序,您将创建一个 Note 模型和一个 Note 对象和输入类型。 Note 模型将表示将存储您的笔记的数据库表,而 Note 对象和输入类型将定义存在于 Note 对象上的字段和参数。

首先,使用 Rails 提供的 generate model 子命令创建一个 Note 模型,并指定模型的名称及其列和数据类型。 在终端窗口中运行以下命令:

rails generate model note title:string:index body:text

此命令创建具有两个字段的 Note 模型:title,类型为 string,和 body,类型为 text。 该命令还在 title 列上添加数据库 index。 它生成这两个文件:

  • 位于 app/models/note.rbnote.rb 文件。 该文件将保存所有与模型相关的逻辑。
  • 位于 db/migrate/20200617173228_create_notes.rb20200617173228_create_notes.rb 文件(文件开头的编号会有所不同,具体取决于您运行命令的日期)。 这是一个迁移文件,其中包含在数据库中创建相应的 notes 表的指令。

要执行迁移文件中的指令,您将使用 db:migrate 子命令来执行迁移文件中的指令。 在终端窗口中运行以下命令:

rails db:migrate

命令成功运行后,您将看到类似于以下内容的输出:

Output== 20200617173228 CreateNotes: migrating ======================================
-- create_table(:notes)
   -> 0.0134s
-- add_index(:notes, :title)
   -> 0.0073s
== 20200617173228 CreateNotes: migrated (0.0208s) =============================

有了音符模型,接下来您将创建一个 NoteType。 一个有效的音符对象应该有 idtitletext。 在终端窗口中运行以下命令以创建 NoteType

rails generate graphql:object Note id:ID! title:String! body:String!

该命令指示 Rails 创建一个名为 Note 的 GraphQL 对象类型,其中包含三个字段:一个类型为 IDid 字段,以及 title 和 [ X163X] 字段,每个字段都有一个 String 类型。 附加到字段类型的感叹号 (!) 表示该字段不应为空,这意味着该字段不应返回空值。 不可为空的字段很重要,因为它们作为一种验证形式,可以保证在查询 GraphQL 对象时必须存在哪些字段。

运行上述命令会创建一个位于 app/graphql/types/note_type.rbnote_type.rb 文件,其中包含一个具有三个不可为空字段的 Types::NoteType 类。

最后,您将创建一个 NoteInput 类型来定义创建注释所需的参数。 首先在 app/graphql/types 下创建一个 input 目录。 输入目录将容纳输入类型:

mkdir ~/rails_graphql/app/graphql/types/input

注意: 在输入目录中创建输入类型不是必须的; 这只是一个共同的约定。 您可以决定将所有类型保留在 types 目录下,并在访问时排除在 Input 模块下嵌套类。


~/rails_graphql/app/graphql/types/input目录下,创建一个note_input_type.rb文件:

nano ~/rails_graphql/app/graphql/types/input/note_input_type.rb

将以下代码添加到文件中以定义 Input 类型的字段:

~/rails_graphql/app/graphql/types/input/note_input_type.rb

module Types
  module Input
    class NoteInputType < Types::BaseInputObject
      argument :title, String, required: true
      argument :body, String, required: true
    end
  end
end

note_input_type.rb 文件中,您添加了一个 Types::Input::NoteInputType 类,它继承自 Types::BaseInputObject 类并接受两个必需的参数; titlebody,都是字符串类型。

您已经为您的笔记应用程序创建了一个模型和两种 GraphQL 类型。 在下一步中,您将创建查询以获取现有笔记。

第 4 步 — 为应用程序创建查询

你的 GraphQL 驱动的 API 正在逐渐融合在一起。 在这一步中,您将创建两个查询; 一个通过 id 获取单个音符,另一个获取所有音符。 GraphQL query 类型处理数据的获取,可以比作 REST 中的 GET 请求。

首先,您将创建一个查询来获取所有笔记。 首先,创建一个 queries 目录来存放所有查询:

mkdir ~/rails_graphql/app/graphql/queries

app/graphql/queries 目录中,创建一个 base_query.rb 文件,所有其他查询类都将从该文件继承:

nano ~/rails_graphql/app/graphql/queries/base_query.rb

将以下代码添加到 base_query.rb 文件中以创建其他查询类将从中继承的 BaseQuery 类:

~/rails_graphql/app/graphql/queries/base_query.rb

module Queries
  class BaseQuery < GraphQL::Schema::Resolver
  end
end

base_query.rb 文件中,您添加了一个从 GraphQL::Schema::Resolver 类继承的 Queries::BaseQuery 类。 GraphQL::Schema::Resolver 类是一个容器,可以保存属于 field 的逻辑。 它可以使用 resolver: 关键字附加到 field

Queries::BaseQuery 类还可以包含您打算在多个查询类中重用的任何代码。

接下来,在queries目录下创建一个fetch_notes.rb文件。 该文件将包含获取所有现有笔记的逻辑,并将附加到查询类型文件中的 field

nano ~/rails_graphql/app/graphql/queries/fetch_notes.rb

将以下代码添加到文件中以定义返回对象类型并解析请求的注释:

~/rails_graphql/app/graphql/queries/fetch_notes.rb

module Queries
  class FetchNotes < Queries::BaseQuery

    type [Types::NoteType], null: false

    def resolve
      Note.all.order(created_at: :desc)
    end
  end
end

fetch_notes.rb 文件中,您创建了一个 Queries::FetchNotes 类,它继承了之前创建的 Queries::BaseQuery。 该类有一个返回 type 声明,声明此查询返回的数据应该是已创建的 NoteType 的数组。

Queries::FetchNotes 还包含一个 resolve 方法,该方法返回所有现有笔记的数组,这些笔记按创建日期降序排列。

FetchNotes 查询已准备好接收和返回笔记请求,但 GraphQL 仍然不知道它的存在,要解决此问题,请打开位于 app/graphql/types/query_type.rb 的 GraphQL 查询类型文件:

nano ~/rails_graphql/app/graphql/types/query_type.rb

query_type.rb 文件是所有 GraphQL query 类型的入口点。 它包含查询字段及其各自的解析器方法。 将文件中的示例代码替换为以下内容:

~/rails_graphql/app/graphql/types/query_type.rb

module Types
  class QueryType < Types::BaseObject
    # Add root-level fields here.
    # They will be entry points for queries on your schema.

    field :fetch_notes, resolver: Queries::FetchNotes
  end
end

query_type.rb 文件中,您添加了 fetch_notes 字段并使用 resolver: 将其附加到 Queries::FetchNotes 类。 这样,每当调用 fetch_notes 查询时,它都会执行 Queries::FetchNotes 类的 resolve 方法中的逻辑。

为了测试您的查询,您需要获取一些数据,但您的数据库中目前没有任何注释。 您可以通过向数据库添加一些种子数据来解决此问题。 打开位于 db/seeds.rbseeds.rb 文件:

nano ~/rails_graphql/db/seeds.rb

将以下代码添加到文件中以创建五个注释:

~/rails_graphql/db/seeds.rb

5.times do |i|
  Note.create(title: "Note #{i + 1}", body: 'Lorem ipsum saves lives')
end

添加代码后保存并关闭文件。

在另一个终端窗口中打开项目的根目录,然后运行以下命令来运行 seed.rb 文件中的代码:

rails db:seed

这将在数据库中创建 5 个注释。

数据库中的数据和开发服务器正在运行,在浏览器中导航到 localhost:3000/graphiqlhttp://your_server_ip:3000/graphiql 以打开 GraphiQL IDE。 在编辑器的左侧,输入以下查询:

query {
  fetchNotes {
    id
    title
    body
  }
}

这个 GraphQL 查询声明了一个 query 操作,表示您要发出查询请求。 在查询操作中,您调用了与 API 中声明的 fetch_notes 查询字段匹配的 fetchNotes 字段,并将这些字段包含在您希望在响应中返回的注释中。

单击标题中的播放图标按钮。 您将在输出窗格中看到类似于以下内容的响应:

{
  "data": {
    "fetchNotes": [
      {
        "id": "5",
        "title": "Note 5",
        "body": "Lorem ipsum saves lives"
      },
      {
        "id": "4",
        "title": "Note 4",
        "body": "Lorem ipsum saves lives"
      },
      {
        "id": "3",
        "title": "Note 3",
        "body": "Lorem ipsum saves lives"
      },
      {
        "id": "2",
        "title": "Note 2",
        "body": "Lorem ipsum saves lives"
      },
      {
        "id": "1",
        "title": "Note 1",
        "body": "Lorem ipsum saves lives"
      }
    ]
  }
}

响应包含一个包含 5 个注释的数组,这些注释与左侧查询中声明的字段相匹配。 如果您删除编辑器左侧查询中的某些字段并重新运行查询,您会收到仅包含您请求的字段的响应。 这就是 GraphQL 的强大之处。

接下来,您将创建另一个查询以通过 id 获取笔记。 此查询将类似于 fetch_notes 查询,只是它将接受 id 参数。 继续在查询目录中创建一个 fetch_note.rb 文件:

nano ~/rails_graphql/app/graphql/queries/fetch_note.rb

将以下代码添加到文件中以查找并返回带有提供的 id 的注释:

~/rails_graphql/app/graphql/queries/fetch_note.rb

module Queries
  class FetchNote < Queries::BaseQuery
    type Types::NoteType, null: false
    argument :id, ID, required: true

    def resolve(id:)
      Note.find(id)
    rescue ActiveRecord::RecordNotFound => _e
      GraphQL::ExecutionError.new('Note does not exist.')
    rescue ActiveRecord::RecordInvalid => e
      GraphQL::ExecutionError.new("Invalid attributes for #{e.record.class}:"\
        " #{e.record.errors.full_messages.join(', ')}")
    end
  end
end

这定义了一个从 Queries::BaseQuery 类继承的 Queries::FetchNote 类。 此类不仅返回必须为 NoteType 的单个项目,它还接受具有 ID 类型的 id 参数。 resolve 方法接收提供的 id 参数,然后找到并返回带有提供的 id 的注释。 如果不存在注释或发生错误,则将其救出并作为 GraphQL::ExecutionError 返回。

接下来,将 Queries::FetchNote 类附加到查询类型文件中的查询字段。 在编辑器中打开 query_type.rb 文件:

nano ~/rails_graphql/app/graphql/types/query_type.rb

将以下代码添加到为 fetch_notes 定义解析器的文件中:

~/rails_graphql/app/graphql/types/query_type.rb

module Types
  class QueryType < Types::BaseObject
    # Add root-level fields here.
    # They will be entry points for queries on your schema.

    field :fetch_notes, resolver: Queries::FetchNotes
    field :fetch_note, resolver: Queries::FetchNote
  end
end

要测试您的新查询,请确保您的服务器正在运行并在浏览器中导航到 localhost:3000/graphiqlhttp://your_server_ip:3000/graphiql 以打开 GraphiQL IDE。 在编辑器的左侧,输入以下查询:

query {
  fetchNote(id: 1) {
    id
    title
    body
  }
}

此查询操作请求一个 fetchNote 字段,该字段对应于 fetch_note 查询字段,并传递一个 id 参数。 它指定我们希望在响应中返回三个字段。

通过单击标题中的 Play 图标按钮运行查询。 您将在输出窗格中收到如下响应:

{
  "data": {
    "fetchNote": {
      "id": "1",
      "title": "Note 1",
      "body": "Lorem ipsum saves lives"
    }
  }
}

响应包含与请求的 id 匹配的单个注释,其字段与请求中的字段匹配。

在此步骤中,您创建了 GraphQL 查询以从您的 API 中获取注释。 接下来,您将编写突变以创建注释。

第 5 步 — 创建 GraphQL 突变以修改注释

除了查询之外,GraphQL 还为修改服务器端数据的操作定义了一个 mutation 类型。 正如 REST 提供 POSTPUTPATCHDELETE 请求来创建、更新和删除资源一样,GraphQL 的 mutation 类型定义导致服务器端写入的操作约定。 在此步骤中,您将创建一个用于添加新注释的突变。

graphQL-ruby 包括两个用于编写突变的类。 他们是:

  • GraphQL::Schema::Mutation:这是用于编写突变的通用基类。 如果您不希望突变中需要 input 参数,则应使用此类。
  • GraphQL::Schema::RelayClassicMutation:这是一个带有一些约定的基类; 一个名为 clientMutationId 的参数始终插入到响应中,以及接受一个名为 input 的参数的突变。 当您使用 install generator 将样板 GraphQL 文件添加到项目中时,默认使用此类。

在位于 app/graphql/mutationsmutations 目录中创建一个 add_note.rb 文件:

nano ~/rails_graphql/app/graphql/mutations/add_note.rb

将以下代码添加到文件中以定义添加新注释的突变:

~/rails_graphql/app/graphql/mutations/add_note.rb

module Mutations
  class AddNote < Mutations::BaseMutation
    argument :params, Types::Input::NoteInputType, required: true

    field :note, Types::NoteType, null: false

    def resolve(params:)
      note_params = Hash params

      begin
        note = Note.create!(note_params)

        { note: note }
      rescue ActiveRecord::RecordInvalid => e
        GraphQL::ExecutionError.new("Invalid attributes for #{e.record.class}:"\
          " #{e.record.errors.full_messages.join(', ')}")
      end
    end
  end
end

这定义了一个从 Mutations::BaseMutation 类继承的 Mutations::AddNote 类,该类是您在安装 GraphQL-Ruby gem 时运行 install generator 时创建的类之一。 Mutations::AddNote 类接收名称为 params 和类型为 NoteInputTypeargument,这是您在步骤 3 中创建的。 它还返回一个名为 notefield,它必须是非空的 NoteType 类型。

类的 resolve 方法接收 params 并将其转换为用于创建和返回包含新注释的新哈希的哈希。 如果在创建笔记时出现错误,错误将被挽救并以 GraphQL::ExecutionError 的形式返回。

注意: 变异中的 resolve 方法必须返回一个哈希,其符号与 field 名称匹配。


与查询一样,必须使用 mutation: 关键字将 Mutations::AddNote 突变附加到突变字段。

在编辑器中打开位于 app/graphql/types/mutation_type.rb 的突变类型文件:

nano ~/rails_graphql/app/graphql/types/mutation_type.rb

将文件中的代码替换为以下代码,这会为 add_note 添加一个字段及其对应的变异类:

~/rails_graphql/app/graphql/types/mutation_type.rb

module Types
  class MutationType < Types::BaseObject
    field :add_note, mutation: Mutations::AddNote
  end
end

在此代码中,您向突变类型文件添加了一个 add_note 字段,并使用 mutation: 关键字将其附加到 Mutations::AddNote 类。 当调用 add_note 突变时,它会运行 Mutations::AddNote 类的 resolve 方法中的代码。

要测试您的新突变,请在浏览器中导航到 localhost:3000/graphiqlhttp://your_server_ip:3000/graphiql 以打开 GraphiQL IDE。 在编辑器的左侧,输入以下查询:

mutation {
  addNote(input: { params: { title: "GraphQL notes", body: "A long body of text about GraphQL"  }}) {
    note {
      id
      title
      body
    }
  }
}

这声明了一个带有 addNote 字段的突变操作,该字段接受单个 input 参数,该参数反过来接受具有与 NoteInputType 匹配的键的 param 对象。 变异操作还包括一个与 Mutations::AddNote 类返回的 note 字段匹配的 note 字段。

在 GraphiQL 中运行突变,您将在输出窗格中看到以下结果:

{
  "data": {
    "addNote": {
      "note": {
        "id": "6",
        "title": "GraphQL notes",
        "body": "A long body of text about GraphQL"
      }
    }
  }
}

返回的响应是新创建的注释,其中包含突变请求中请求的字段。

随着您的 add_note 变异现在工作,您的 API 可以使用 GraphQL 查询和变异来获取和创建注释。

结论

在本教程中,您使用 Ruby on Rails 创建了一个笔记记录 API 应用程序,使用 PostgreSQL 作为数据库,GraphQL 作为 API 查询语言。 您可以在其 官网 上了解更多关于 GraphQL 的信息。 GraphQL-Ruby gem 网站还包含一些指南,可帮助您在 Rails 中使用 GraphQL。