GraphQL Ruby的入门-基本的增删改查操作
这是关于GraphQL Ruby的介绍。
我们将以教程形式总结如何创建一个简单的API服务器,用于Todo应用程序。
以下的代码都可以在以下存储库中找到:https://github.com/kawamataryo/practice-graphql-ruby-2
GraphQL Ruby 是什么?
这个Gem用于在Ruby上建立GraphQL API服务器。与其他库不同的是,它不需要直接编写GraphQL模式,而是在Ruby代码中定义模式与实现。
安装
我们将从这里开始创建一个任务管理应用的API服务器。
像往常一样,我们使用rails new命令创建项目。跳过不必要的模块。
rails new todo-app --skip-action-mailer --skip-action-mailbox --skip-action-text --skip-active-storage --skip-action-cable --skip-javascript --skip-system-test --skip-webpack-install
当你启动Rails S时,将会显示一个熟悉的界面。
cd todo-app
bundle exec rails s
引入GraphQL Ruby
下一步是引入GraphQL Ruby。
请在Gemfile中添加以下内容作为补充。
GraphQL是GraphQL的Ruby版本。
graphql-rails是用于在浏览器上执行GraphQL客户端GraphiQL的工具。
gem 'graphql'
gem 'graphiql-rails', group: :development
在执行bundle install后,运行generate命令来创建相关文件。
bundle i
bundle exec rails generate graphql:install
重新启动本地服务器并访问以下内容。
让我们启动GraphiQL控制台,并执行以下查询。
query {
testField
}
你能看到「无事Hello World」的显示吗?这意味着GraphQL Ruby的引入已经完成了。
※截至2020年4月19日,似乎在GraphiQL中出现以下错误。
Asset `graphiql/rails/application.css` was not declared to be precompiled in production.
Declare links to your assets in `app/assets/config/manifest.js`
如果是这种情况,我们应该在 config/environments/development.rb 文件的 config 部分末尾添加以下内容。
config.assets.precompile += ['graphiql/rails/application.js', 'graphiql/rails/application.css']
获取任务列表的查询
创建一个用于获取任务列表的查询。
让我们使用generate功能创建Task模型,然后执行数据库的迁移。
bundle exec rails g model Task title:string note:string completed:boolean
bundle exec rails db:migrate
接著使用graphql-ruby的生成器來創建Task的Type。
這個Type將成為響應的型別。
rails g graphql:object TaskType id:ID! title:String! note:String completed_at:Boolean
创建了 app/graphql/types/task_type.rb 文件。
module Types
class TaskType < Types::BaseObject
field :id, ID, null: false
field :title, String, null: false
field :note, String, null: true
field :completed, Boolean, null: true
end
end
接下来,创建名为resolvers的目录,并创建Tasks的解析器。
在resolve函数中,使用Task.all进行返回。这将成为响应结果。
module Resolvers
class Tasks < GraphQL::Schema::Resolver
type [Types::TaskType], null: false
def resolve
Task.all
end
end
end
然后在query_type.rb中声明将tasksfield与解析器相关联。
module Types
class QueryType < Types::BaseObject
field :tasks, resolver: Resolvers::Tasks
end
end
上述的第一个查询已经实现完成了。
由于没有初期数据,执行 bundle exec rails c 命令来启动 Rails 控制台,并添加一些任务。
Task.create!(title: '買い物', note: 'たまご, 牛乳')
Task.create!(title: '掃除', note: 'リビング')
现在确认的准备工作已经完成了。
让我们通过访问 GraphiQL 并执行以下查询来尝试一下。
query {
tasks {
title
note
completed
}
}
获取了Task.all的结果。graphql-ruby对ActiveRecord进行解析,然后返回GraphQL数据。
添加任务的变更
让我们添加一个任务功能。
首先,在mutations目录中创建create_task.rb文件。
module Mutations
class CreateTask < GraphQL::Schema::Mutation
argument(:title, String, required: true)
argument(:note, String, required: false)
type Types::TaskType
def resolve(title: nil, note: nil)
Task.create!(
title: title,
note: note
)
end
end
end
出于简化的目的,我们将直接继承GraphQL::Schema::Mutation而不是继承BaseMutation。
然后在mutation_type.rb中声明与:create_taskfield绑定的CreateTask变异。
module Types
class MutationType < Types::BaseObject
field :create_task, mutation: Mutations::CreateTask, null: false
end
end
应该可以仅凭这个就能创建任务。
让我们执行以下变异。
mutation {
createTask(title: "勉強" note: "graphql-rubyのチュートリアル") {
id
title
note
completed
}
}
你成功创建了一个无事的任务。
任务更新的突变
接下来,我们将创建一个用于更新任务的Mutation。请将created_task.rb复制到mutations目录中,并创建一个名为update_task.rb的文件。
module Mutations
class UpdateTask < GraphQL::Schema::Mutation
argument(:id, ID, required: true)
argument(:completed, Boolean, required: true)
argument(:title, String, required: false)
argument(:note, String, required: false)
type Types::TaskType
def resolve(id: nil, completed: nil, title: nil, note: nil)
task = Task.find(id)
task.completed = completed
task.title = title if title
task.note = note if note
task.tap(&:save!)
end
end
end
然后在mutation_type.rb中添加update_task。
module Types
class MutationType < Types::BaseObject
field :create_task, mutation: Mutations::CreateTask, null: false
field :update_task, mutation: Mutations::UpdateTask, null: false # こちらを追加
end
end
请使用GraphiQL控制台执行以下变异来完成更新。
mutation {
update_task(id: 3 completed: true) {
id
title
note
completed
}
}
删除任务的变更
我們將在最後實現刪除任務的功能。
我們將創建delete_task.rb文件。
由於我們希望刪除的回應不是Task對象,而是deleted: Boolean,因此在解析器內定義了一個繼承自Types::BaseObject的DeleteResultType,並用type指定。
module Mutations
class DeleteTask < GraphQL::Schema::Mutation
argument(:id, ID, required: true)
class DeleteResultType < Types::BaseObject
field :deleted, Boolean, null: false
end
type DeleteResultType
def resolve(id: nil)
result = Task.find(id).destroy
{ deleted: result }
end
end
end
我会在mutation_type.rb中加入delete_task。
module Types
class MutationType < Types::BaseObject
field :create_task, mutation: Mutations::CreateTask, null: false
field :update_task, mutation: Mutations::UpdateTask, null: false
field :delete_task, mutation: Mutations::DeleteTask, null: false # これを追加
end
end
如果你能做到这一点,那么就尝试执行以下的变异操作吧。
mutation {
deleteTask(id: 2) {
deleted
}
}
你成功刪除了那個無事任務呢。
这样一来,TODO应用程序的CRUD处理就完成了。
下一步
请务必尝试一下在GraphQL官方教程中介绍的未能在此处介绍的身份验证和分页等实现方法,作为下一步的尝试。
最后
以上是對GraphQL Ruby的介紹。
在Rails中快速構建GraphQL的API伺服器是很不錯的。
它可以與REST API共存,所以在創建新API時可以成為一個選擇。
请参考
- https://employment.en-japan.com/engineerhub/entry/2018/12/26/103000