Ruby on Rails GraphQL API 教程:从 'rails new' 到首次查询
概述
什么是GraphQL?
创建 Rails 应用
添加 GraphQL
填写新的 GraphQL 文件
撰写我们的第一个查询
结论
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
这周我一直在做一项课后技术挑战,要求我深入学习GraphQL并创建一个简单的 API。我以前从未接触过 GraphQL,所以我选择继续使用 Ruby on Rails 来学习它。
本教程旨在逐步介绍如何使用 Ruby on Rails 和Ruby gem 'graphql'创建 GraphQL API 。
它主要改编自Matt Boldt 的这篇精彩教程,但也有一些明显的不同之处:
-
我将使用Insomnia REST 客户端进行 API 调用,而不是使用'graphiql' IDE——如果您还没有安装它,请立即安装!
-
我将从简单的模型开始
Order,Payment但最终(在以后的文章中)会扩展到更复杂的关系(并实现诸如直接在模型和has_many声明上使用自定义方法过滤对象等功能)。 -
我将在后续文章中探讨 GraphQL 中 Mutations 部分的“幂等性” ,并采用Todd Jefferson 在这篇精彩文章中介绍的策略。
概述
在本文中,我们将介绍以下步骤:
- 创建一个 Rails API
- 添加一些模型
- 添加 GraphQL
- 编写并执行我们的第一个 GraphQL 查询
GraphQL 有两种与数据库交互的方式。
- 查询——这使我们能够获取数据(CRUD 中的“读取”操作)。
- 变异——这允许我们更改信息,包括添加、更新或删除数据(CRUD 中的“创建”、“更新”、“销毁”)。
我们将继续专注于让 API 运行起来,并理解我们的第一个简单查询。
让我们开始吧!
什么是GraphQL?
GraphQL 是一种查询语言,可用于获取和修改数据库中的数据。它允许用户通过指定要返回的特定模型和字段来控制要获取的数据。此外,它还是强类型的,因此您可以确切地知道接收到的数据类型!
GraphQL 与语言无关,因此我们将使用的 Ruby 实现是Ruby gem 'graphql'。它为我们提供了特定的文件结构和一些命令行工具,以便轻松地将 GraphQL 功能添加到我们的 Rails API 中。
创建 Rails 应用
'rails new'
在终端中运行以下命令,创建一个名为devto-graphql-ruby-api的新 Rails 项目。您可以省略任何 `--skip` 标志,但它们都不会被使用:
$ rails new devto-graphql-ruby-api --skip-yarn --skip-action-mailer --skip-action-cable --skip-sprockets --skip-coffee --skip-javascript --skip-turbolinks --api
生成模型
在目录下,我们来创建我们的Order模型Payment:
$ rails g model Order description:string total:float
$ rails g model Payment order_id:integer amount:float
我更喜欢手动设置 has_many-belongs_to 关系,所以让我们让Payments 属于 an Order:
# app/models/order.rb
class Order < ApplicationRecord
has_many :payments
end
# app/models/payment.rb
class Payment < ApplicationRecord
belongs_to :order
end
创建数据库
运行$ rails db:create以创建(默认)SQLite3 开发数据库。
运行迁移
运行此程序$ rails db:migrate将我们的模型添加到数据库。
添加种子数据
添加一些示例对象来填充我们的数据库:
# db/seeds.rb
order1 = Order.create(description: "King of the Hill DVD", total: 100.00)
order2 = Order.create(description: "Mega Man 3 OST", total: 29.99)
order3 = Order.create(description: "Punch Out!! NES", total: 0.75)
payment1 = Payment.create(order_id: order1.id, amount: 20.00)
payment2 = Payment.create(order_id: order2.id, amount: 1.00)
payment3 = Payment.create(order_id: order3.id, amount: 0.25)
然后运行程序$ rails db:seed将数据添加到数据库。
现在我们准备开始在模型之上添加 GraphQL 了!
添加 GraphQL
将 'graphql' gem 添加到 Gemfile 中
# Gemfile
gem 'graphql'
然后运行程序$ bundle install将该 gem 安装到应用程序中。
使用“rails generate”命令安装GraphQL
运行此命令$ rails generate graphql:install。这将把/graphql/目录添加到应用程序的主目录中,并在该目录下添加一个 GraphQL 特定的控制器/controllers/graphql_controller.rb。
为模型添加 GraphQL 对象
现在我们需要创建与我们的模型相匹配的GraphQL对象:
$ rails generate graphql:object order$ rails generate graphql:object payment
填写新的 GraphQL 文件
好了,我们现在有了构建第一个查询所需的所有文件和目录!但是,其中一些文件还需要添加一些代码。
定义 GraphQL 类型及其字段
GraphQL 类型由字段定义,这些字段告诉我们可以从中获取哪些数据:
# app/graphql/types/payment_type.rb
module Types
class PaymentType < Types::BaseObject
field :id, ID, null: false
field :amount, Float, null: false
end
end
这样我们就可以检索PaymentType包含一个id字段(具有特殊 ID 主键)和一个amount浮点型字段的对象。由于这两个字段都被设置为 `float`,因此在null: false查询响应nil中,如果任一字段包含 `float` 值,都会引发错误。
我们的 GraphQL 对象继承自 Types::BaseObject。因此,当我们定义自己的对象时class PaymentType < Types::BaseObject,我们就拥有了一个Types::PaymentType可用的 Types::BaseObject。我们可以使用这些自定义类型来定义从每个字段返回的内容。
让我们来看看如何Types::PaymentType使用OrderType:
# app/graphql/types/order_type.rb
module Types
class OrderType < Types::BaseObject
field :id, ID, null: false
field :description, String, null: false
field :total, Float, null: false
field :payments, [Types::PaymentType], null: false
field :payments_count, Integer, null: false
def payments_count
object.payments.size
end
end
end
这里有几点需要注意:
- 因为该
Order模型有id、description和列total,我们可以简单地为它们创建一个字段并检索它们的数据。 - 由于我们之间存在 has_many-belongs_to 关系,我们还可以创建一个
payments字段来返回Types::PaymentType属于每个对象的所有对象Order。 - 但是,
Order它没有payments_count列——所以我们定义了一个payments_count()方法来返回一个表示数组长度的整数payments。- 注意:在这些自定义字段方法中,我们需要通过访问
Order“s” ——别忘了关键的!paymentsobject.paymentsobject
- 注意:在这些自定义字段方法中,我们需要通过访问
在 QueryType 上定义字段
我们几乎可以开始编写第一个查询了,但首先,我们需要告诉主查询类型(QueryType)它应该接收这个查询。当 GraphQL 收到查询请求(而不是变更请求)时,它会被路由到查询类型类。和上面的类型一样,我们将通过字段定义可能的查询方法。
我们的第一个查询很简单,就是检索Order数据库中的所有 s。在class QueryType声明中,我们将添加一个字段,该字段返回一个数组Types::OrderType:
# app/graphql/types/query_type.rb
module Types
class QueryType < Types::BaseObject
field :all_orders, [Types::OrderType], null: false
def all_orders
Order.all
end
end
end
如上所述,我们all_orders()在同名字段下定义我们的方法,并告诉它隐式返回所有Orders。
一切准备就绪!我们可以打开 Insomnia 并编写第一个查询语句,Order从数据库中获取所有数据。
撰写我们的第一个查询
GraphQL 查询格式
以下是我们的第一个查询语句:
query {
allOrders {
id
description
total
payments {
id
amount
}
paymentsCount
}
}
在顶部,我们将请求定义为query {}。
在查询内部,我们all_orders通过调用QueryType 来获取查询类型allOrders {}。是的,别忘了把蛇形命名法改成驼峰命名法!
在内部allOrders {},我们从模型中选择要返回的字段Order。这些字段与我们在之前定义的字段相同app/graphql/types/order_type.rb。您可以选择要接收的字段!
请注意,对于我们的payments {}字段,我们还必须定义要Types::PaymentType接收的字段。可用的字段是我们之前定义的那些字段app/graphql/types/payment_type.rb。
该paymentsCount字段将对 运行该payments_count方法Types::OrderType,并返回相应的值。
让我们把这个查询导入到 Insomnia 中,测试一下我们的 API!
在失眠症中执行查询
运行$ rails s以启动 Rails API 服务器,地址为http://localhost:3000/graphql。
打开 Insomnia,创建一个新的 POST 请求。在请求文本编辑器的左上角,确保 POST 请求的格式设置为“GraphQL 查询”。
请添加以上代码query。然后发送出去,看看返回结果是什么:
哇!我们的数据整理得井井有条——而且完全符合我们的要求!
让我们运行一个类似的查询,但使用更少的字段:
query {
allOrders {
description
total
payments {
amount
}
}
}
结果:
完美!如果我们不需要ids 或paymentsCount,那就完全不需要将它们包含在查询中!
结论
我们现在有了一个非常简单的 API,可以使用 GraphQL 从数据库查询数据!但是,由于 GraphQL 查询只能检索数据,我们无法使用当前的代码对数据库进行任何更改。
这就是变异发挥作用的地方!我们将在下一期节目中详细介绍。 ;)
再次感谢Matt Boldt 和他超棒的 Rails GraphQL 教程,让我能够走到今天!<3
关于在 Rails 中使用 GraphQL,或者 GraphQL 本身,有什么技巧或建议吗?欢迎在下方分享!
文章来源:https://dev.to/isalevine/ruby-on-rails-graphql-api-tutorial-from-rails-new-to-first-query-76h

