文章目录
- 1.graphql的基本概念
- 2.graphql的组成部分
- 3.创建一个基于graphql的rails项目
- step1:创建一个rails 项目,并生成对应的model**
- step2: 引入gem包
- step3:在user.rb里面加入 has_many :books
- step4: 创建graphql目录和2个新的自定义类型User和Post
- step5: 在routes.rb中,创建app/controllers/graphql_controller.rb#execute,作为api访问的入口
- step6: 创建GraphQL的类型(Type)
- step7: 定义主查询类型
- step8: 在query_type文件里面,定义:users和:user的字段,以及他们的方法
- step9: 测试查询
- step10: Mutations(变更 )
- step11: 创建CreateUser的mutation。
- step12: 将新变更mutation添加到主突变类型类中,以便暴露给我们的API。
- step13 创建用户测试
1.graphql的基本概念
- GraphQL 是一种针对 Graph(图状数据)进行查询特别有优势的 Query Language(查询语言),所以叫做 GraphQL。
- 它跟 SQL 的关系是共用 QL 后缀,就好像「汉语」和「英语」共用后缀一样,但他们本质上是不同的语言。
- GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。
- 向你的 API 发出一个 GraphQL 请求就能准确获得你想要的数据,不多不少
2.graphql的组成部分
- Fields: 是关于请求对象上的特定字段
- Arguments:请求时传递的参数以及它们是什么对象类型, 这是必需的。这有点类似于在Rails控制器中定义强参数,这里对进入的内容进行更细粒度的控制。
- Types: 类型,用于定义数据类型,或者定义Rails模型model,类型包括根据-Queries/Mutations中的请求相应数据的字段和函数。类型也可以是静态的,比如:String或ID,这些内置在服务器端的library中。
- Queries:从API获取特定的数据。将查询设置为只读,就像Rest里面的Get,但是查询不仅是Get。
- Mutations: 变更,对API数据的修改,比如:create、update、destroy。
- Resolver解析器:resolve方法是执行ActiveRecord命令的地方。他返回一个带有和上面定义的字段名称一样的键的hash.
- Functions: 方法、功能,给上面的字段提供数据,
3.创建一个基于graphql的rails项目
step1:创建一个rails 项目,并生成对应的model**
rails new graphql_fun_demo
rails g model User email:string name:string
rails g model Post user:belongs_to title:string body:text
rails db:migrate
step2: 引入gem包
- gem ‘faker’
- gem ‘graphiql-rails’
step3:在user.rb里面加入 has_many :books
在seeds.rb文件,通过faker创建一些数据
5.times do
user = User.create(name: Faker::Name.name, email: Faker::Internet.email)
5.times do
user.posts.create(title: Faker::Lorem.sentence(word_count: 3),
body: Faker::Lorem.paragraph(sentence_count: 3))
end
end
step4: 创建graphql目录和2个新的自定义类型User和Post
rails g graphql:install
rails g graphql:object user
rails g graphql:object post
step5: 在routes.rb中,创建app/controllers/graphql_controller.rb#execute,作为api访问的入口
if Rails.env.development?
mount GraphiQL::Rails::Engine, at: '/graphql', graphql_path:"graphql#execute"
end
启动项目,访问http://localhost:3000/graphiql,就可以看到测试api接口的页面
step6: 创建GraphQL的类型(Type)
module Types
class UserType < Types::BaseObject
# null: false 不允许为空
field :id, ID, null: false
field :name, String, null: true
field :email, String, null: true
field :posts, Types::PostType, null: true
field :posts_count, Integer, null: true
def posts_count
object.posts.size
end
end
end
module Types
class PostType < Types::BaseObject
field :id, ID, null: false
field :user_id, Integer, null: true
field :title, String, null: true
field :body, String, null: true
end
end
step7: 定义主查询类型
query_type.rb和mutation_type.rb这两种传入请求的路由,定义在模式schema里面,他们和Rails路由和资源有些相似。分别为查询和修改特定的数据
class GraphqlApiSchema < GraphQL::Schema
mutation(Types::MutationType)
query(Types::QueryType)
end
step8: 在query_type文件里面,定义:users和:user的字段,以及他们的方法
module Types
class QueryType < Types::BaseObject
field :users, [Types::UserType], null: false
# users方法返回UserType类型的一组对象。
def users
User.all
end
# user方法接收一个类型为ID的:id的参数,返回一个UserType对象,(ID是一个内置的类型)
field :user, Types::UserType, null: false do
argument :id, ID, required: true
end
def user(id:)
User.find(id)
end
end
end
step9: 测试查询
- 查询所有用户信息
query{
users{
id
name
email
postsCount
}
}
- 查询指定id的用户信息
query{
user(id:2){
id
name
email
postsCount
}
}
step10: Mutations(变更 )
Mutations允许创建、修改、销毁数据,我们设置一个基类,用来扩展CreateUser的mutation。
module Mutations
class BaseMutation < GraphQL::Schema::RelayClassicMutation
end
end
step11: 创建CreateUser的mutation。
class Mutations::CreateUser < Mutations::BaseMutation
argument :name, String, required: true
argument :email, String, required: true
# 和上面查询字段概念相同,接收参数创建对象,同时希望返回一个user带有我们的新模型的字段,并附带一个errors数组。
field :user, Types::UserType, null: false
field :errors, [String], null: false
def resolve(name:, email:)
user = User.new(name: name, email: email)
if user.save
{
user: user,
errors: [],
}
else
{
user: nil,
errors: user.errors.full_message
}
end
end
end
step12: 将新变更mutation添加到主突变类型类中,以便暴露给我们的API。
module Types
class MutationType < Types::BaseObject
field :create_user, mutation: Mutations::CreateUser
end
end
step13 创建用户测试
我们传入一个createUser(input: {})对象; 这映射到:create_user接受单个input参数的字段。
mutation{
createUser(input:{
name:"张三",
email:"aa@qq.com"
}){
user{
id
name
email
}
errors
}
}