Using GraphQL in Rails5

2017-02-18 10:44

GraphQL on Rails(一) GraphQL介绍GraphQL on Rails(二) 结合Rails的查询APIGraphQL on Rails(三) 结合Rails的修改API参考了falm的上面三篇文章,不过按照上面描述的并不能稳健的运行起来,所以我就自己动手继续找了一些资料,上面代码似乎年代久远,一些写法可能变化了。

从这里开始

首先你需要一个rails的项目,然后创建一些基础的东西,这边就不多做赘述了,毕竟大家都是成熟的程序员了。

rails new graphql-rails
rails g model Author name:string
rails g model Blog title:string content:string

接下来开始添加GraphQL的一些deps,编辑你的Gemfile

gem "graphql"
gem 'graphiql-rails'

上面文章用了3个,但是其实我只需要这两个就可以了,parser似乎并不是一定需要的组件。然后你需要在app的目录下面创建一些文件

Using GraphQL in Rails50
Structure

这里有一些tricky的地方是上文没有说到的,第一,因为这是一个rails的完整项目,而不是api only,所以你还需要rack-cors去处理CORS的问题,第二就是你需要把graph里面的一些东西加入load_path中才能保证你写的东西能够认出来。

Using GraphQL in Rails51
load_path.png

这些都做好之后写那些schema,type,和mutation就可以了

# author_mutations.rb
module AuthorMutations

  Create = GraphQL::Field.define do
    type -> { AuthorType }
    description 'create a author'

    argument :name, !types.String

    resolve -> (obj, input_fields, ctx)  do
      Author.create(name: input_fields['name'])
    end
  end

end

# query_schema.rb
QuerySchema = GraphQL::Schema.define do
  query QueryType
  mutation MutationType
end

# author_type.rb
AuthorType = GraphQL::ObjectType.define do
  name "Author"
  description "A Author"
  field :id, types.ID
  field :name, types.String
  field :blogs, -> { types[!BlogType] }
end

# blog_type.rb
BlogType = GraphQL::ObjectType.define do
  name "Blog"
  description "A Blog"
  field :id, types.ID
  field :title, types.String
  field :content, types.String
  field :author do
    type AuthorType
    resolve -> (obj, args, ctx) {
      obj.author
    }
  end
end

# mutation_type.rb
MutationType = GraphQL::ObjectType.define do
  name "Mutation"
  description "A Mutation"
  field :CreateAuthor, field: AuthorMutations::Create
end

# query_type.rb
QueryType = GraphQL::ObjectType.define do
  name "Query"
  description "The query root for this schema"

  field :author do
    type AuthorType
    argument :id, !types.ID
    resolve -> (obj, args, ctx) {
      Author.find(args[:id])
    }
  end

  field :blog do
    type BlogType
    argument :id, !types.ID
    resolve -> (obj, args, ctx) {
      Blog.find(args[:id])
    }
  end

  field :authors do
    type !types[!AuthorType]
    resolve -> (obj, args, ctx) do
      Author.all
    end
  end

  field :blogs do
    type !types[!BlogType]
    resolve -> (obj, args, ctx) do
      Blog.all
    end
  end
end

这些基本的东西都放在应该放的地方就可以了。理论上这边就是graph目录里面常用的一些东西了。

然后基础的routes.rb中看起来应该是下面这样的

Rails.application.routes.draw do
  mount GraphiQL::Rails::Engine, at: "/graphql", graphql_path: "queries"
  root to: redirect("/graphql")
  resources :queries
end

# This is a simple queries_controller.rb
class QueriesController < ApplicationController
  def create
    query_string = params[:query]
    query_variables = params[:variables] || {}
    result = QuerySchema.execute(query_string, variables: query_variables)
    render json: result
  end
end

到此就结束了,可以参考上面的文章,巩固一下概念。

Github传送门