发布于 2026-01-06 8 阅读
0

Ruby on Rails GraphQL API Tutorial: From 'rails new' to First Query Overview What is GraphQL? Creating the Rails app Adding GraphQL Filling out the new GraphQL files Writing our first Query Conclusion DEV's Worldwide Show and Tell Challenge Presented by Mux: Pitch Your Projects!

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——如果您还没有安装它,请立即安装!

  • 我将从简单的模型开始OrderPayment但最终(在以后的文章中)会扩展到更复杂的关系(并实现诸如直接在模型和has_many声明上使用自定义方法过滤对象等功能)。

  • 我将在后续文章中探讨 GraphQL 中 Mutations 部分的“幂等性” ,并采用Todd Jefferson 在这篇精彩文章中介绍的策略。

概述

在本文中,我们将介绍以下步骤:

  • 创建一个 Rails API
  • 添加一些模型
  • 添加 GraphQL
  • 编写并执行我们的第一个 GraphQL 查询

GraphQL 有两种与数据库交互的方式。

  1. 查询——这使我们能够获取数据(CRUD 中的“读取”操作)。
  2. 变异——这允许我们更改信息,包括添加、更新或删除数据(CRUD 中的“创建”、“更新”、“销毁”)。

我们将继续专注于让 API 运行起来,并理解我们的第一个简单查询。

让我们开始吧!

什么是GraphQL?

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
Enter fullscreen mode Exit fullscreen mode

我更喜欢手动设置 has_many-belongs_to 关系,所以让我们让Payments 属于 an Order

# app/models/order.rb
class Order < ApplicationRecord
    has_many :payments
end
Enter fullscreen mode Exit fullscreen mode
# app/models/payment.rb
class Payment < ApplicationRecord
    belongs_to :order
end
Enter fullscreen mode Exit fullscreen mode

创建数据库

运行$ 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)
Enter fullscreen mode Exit fullscreen mode

然后运行程序$ rails db:seed将数据添加到数据库。

现在我们准备开始在模型之上添加 GraphQL 了!

添加 GraphQL

将 'graphql' gem 添加到 Gemfile 中

# Gemfile
gem 'graphql'
Enter fullscreen mode Exit fullscreen mode

然后运行程序$ 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
Enter fullscreen mode Exit fullscreen mode

这样我们就可以检索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
Enter fullscreen mode Exit fullscreen mode

这里有几点需要注意:

  • 因为该Order模型有iddescription和列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
Enter fullscreen mode Exit fullscreen mode

如上所述,我们all_orders()在同名字段下定义我们的方法,并告诉它隐式返回所有Orders。

一切准备就绪!我们可以打开 Insomnia 并编写第一个查询语句,Order从数据库中获取所有数据。

撰写我们的第一个查询

GraphQL 查询格式

以下是我们的第一个查询语句:

query {
    allOrders {
        id
        description
        total      
        payments {
            id
            amount
        }
        paymentsCount
    }
}
Enter fullscreen mode Exit fullscreen mode

在顶部,我们将请求定义为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。然后发送出去,看看返回结果是什么:

Insomnia 运行查询并显示返回数据的屏幕截图

哇!我们的数据整理得井井有条——而且完全符合我们的要求!

让我们运行一个类似的查询,但使用更少的字段:

query {
    allOrders {
        description
        total      
        payments {
            amount
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

结果:

Insomnia 运行查询时字段较少,并显示返回数据的屏幕截图

完美!如果我们不需要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