Leon's Blogging

Coding blogging for hackers.

Rails With GraphQL API

| Comments

GraphQL 是 facebook 所開放的查詢語言

GraphQl is a query language for your API

  • GraphQL 是 facebook 所開放的查詢語言,可以透過定義的schema系統將複雜的邏輯拆分成細粒度的資料結構,讓前端能夠透過GraphQL提供的類型查詢系統,自由定製請求數據的能力。
  • GraphQL 本身適合對數據力度小,需求變更頻繁的場景,與 RESTful 相反

GraphQL Look Like

1
2
3
4
5
6
7
8
9
{
  user(id: 1) {
    id,
    name,
    friends {
      name
    }
  }
}

Response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "user" : {
    "id": 1,
    "name": "Marc-Andre Giroux",
    "friends": [
      {
        "name": "Joe Bro"
      },
      {
        "name": "Johny Yolo"
      }
    ]
  }
}

Rails with GraphQL API

graphql-ruby

主要有五個步驟

  • 新增 ruby gem graphql-ruby
  • Declare Query Type
  • Build a Schema
  • Add GraphQL end_point

Ruby gem

1
gem 'graphql'
1
$ bundle install

Declare Query Type

All Types (! marks a field as “non-null”)

  • string
  • int
  • float
  • boolean
  • ID
1
2
3
4
5
6
7
8
9
10
# app/graph/types/post_type.rb
PostType = GraphQL::ObjectType.define do
  name "Post"
  description "A blog post"
  # `!` marks a field as "non-null"
  field :id, !types.ID
  field :title, !types.String
  field :body, !types.String
  field :comments, types[!CommentType]
end
1
2
3
4
5
6
7
# app/graph/types/comment_type.rb
CommentType = GraphQL::ObjectType.define do
  name "Comment"
  field :id, !types.ID
  field :body, !types.String
  field :created_at, !types.String
end

Make sure you add this line to your application.rb for rails to autoload the types

1
2
3
#config/application.rb
config.autoload_paths << Rails.root.join('app', 'graph')
config.autoload_paths << Rails.root.join('app', 'graph', 'types')

Build a Schema

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#app/graph/types/query_type.rb
#query root

QueryType = GraphQL::ObjectType.define do
  name "Query"
  description "The query root of this schema"

  field :post do
    type PostType
    argument :id, !types.ID #argument 可以根據哪些欄位去查詢
    description "Find a Post by ID"
    resolve ->(obj, args, ctx) { Post.find(args["id"]) }
  end
end
1
2
3
4
# app/graph/schema.rb
Schema = GraphQL::Schema.define do
  query QueryType
end

Router

1
2
#config/routes.rb
resources :queries, via: [:post, :options]
1
2
3
4
5
6
7
8
9
# app/controller/queries_controller.rb
class QueriesController < ApplicationController
  def create
    query_string = params[:query]
    query_variables = params[:variables] || {}
    result = BlogSchema.execute(query_string, variables: query_variables)
    render json: result
  end
end

Execute queries

1
curl -XPOST -d 'query={ blog(id: 1) { title content }}' http://localhost:3000/queries

Comments