GraphQL on Rails

GraphQL on Rails

Simple GraphQL introduction and demonstrate steps to integrate GraphQL with a Rails backend. Talked at RubyConf China 2015.

4f0a13793bb53215c3ad94e12b0a57e8?s=128

JunChen Xia

October 12, 2015
Tweet

Transcript

  1. 2.
  2. 9.

    { “data”: { “id”: 123, “title”: “Growth…”, “permalink”: “mirandakerr”, “createdAt”:

    “some time”, “updatedAt”: “another time”, “picture”: “//image.png”, “description”: “…”, “notes”: “…”, “state”: “published”, “screenshot_url”: “…”, “isRetired”: false, … } } { “data”: { “id”: 123, “title”: “Growth…”, “permalink”: “mirandakerr”, “createdAt”: “some time”, “updatedAt”: “another time”, “picture”: “//image.png”, “description”: “…”, “notes”: “…”, “state”: “published”, “screenshot_url”: “…”, “isRetired”: false, … } } Data Over-fetching
  3. 10.

    Client Feature 1(v6) Feature 2(v6) Feature 3(v6) Feature 1(v6) Feature

    1(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 3(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 2(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Feature 1(v6) Server Version Hell Client
  4. 12.

    “The REST interface is designed to be efficient for large-grain

    hypermedia data transfer…” - Dr Roy T Fielding, Author of REST RESTๅᭇአԭय़ᔉଶහഝ࣋ว
  5. 15.
  6. 17.

    { “me”: { “name”: “Junchen Xia”, “picture”: { “height”: 300,

    “width”: 300, “url”: “//image.png” } } } { me { name picture(size: 300) { height width url } } } ىᔮັᧃ
  7. 18.

    { “me”: { “name”: “Junchen Xia”, “smallPic”: { “height”: 50,

    “width”: 50, “url”: “//image.png” }, “bigPic”: { “height”: 300, “width”: 300, “url”: “//bigimage.png” } } } { me { name smallPic: picture(size: 50) { height width url } bigPic: picture(size: 300) { height width url } } } { me { name smallPic: picture(size: 50) { height width url } bigPic: picture(size: 300) { height width url } } } alias
  8. 19.

    { “me”: { “name”: “Junchen Xia”, “friends”: [ { “name”:

    “AAA” }, { “name”: “BBB” } ] } } { me { name friends { name } } } one to many
  9. 20.

    { me { name smallPic: picture(size: 50) { } bigPic:

    picture(size: 300) { } } } fragment pictureParam on picture { height width url } …pictureParam …pictureParam Fragment
  10. 21.

    च๜༷ஷ { me { name picture { height width url

    } } } query object field object
  11. 22.

    { me { name picture { height width url }

    } } type Query { me: User user(id: Int): User }
  12. 23.

    { me { name picture { height width url }

    } } type User { name: String picture(size: Int=50): Picture }
  13. 24.

    { me { name picture { height width url }

    } } type Picture { height: Int width: Int url: String format: String }
  14. 25.

    { name(user) { user.name } picture(user, {size}) { user.picture(size) }

    } type User { name: String picture(size: Int=50): Picture } Resolver
  15. 26.

    { name(user) { user.name } picture(user, {size}) { user.picture(size) }

    } type User { name: String picture(size: Int=50): Picture } Resolver
  16. 27.

    { name(user) { user.name } picture(user, {size}) { user.picture(size) }

    } type User { name: String picture(size: Int=50): Picture } Resolver
  17. 29.

    Server Client page data V1 data V1 page data V2

    data V2 page data V3 data V3 V1 V3 V2 GraphQL
  18. 32.

    Introspection { __schema{ types{ name fields{ name type { name

    } } } } } { "data": { "__schema": { "types": [ { "name": "Query", "fields": [ { "name": "user", "type": { "name": "User" } … }
  19. 38.
  20. 40.

    Ⴒے GraphQL endpoint class GraphqlController < ApplicationController def query render

    json: Schema.execute( params[:query], variables: params[:variables] || {} ) end end
  21. 41.

    Ⴒے GraphQL endpoint class GraphqlController < ApplicationController def query render

    json: Schema.execute( params[:query], variables: params[:variables] || {} ) end end
  22. 43.

    ਧԎquery type QueryType = GraphQL::ObjectType.define do name "Query" description "The

    query root for this schema" field :user do type UserType argument :email, types.String argument :id, types.ID resolve -> (obj, args, ctx) do if args['id'] User.find(args['id']) else User.find_by(email: args['email']) end end end end
  23. 44.

    ਧԎ query type QueryType = GraphQL::ObjectType.define do name "Query" description

    "The query root for this schema" field :user do type UserType argument :email, types.String argument :id, types.ID resolve -> (obj, args, ctx) do if args['id'] User.find(args['id']) else User.find_by(email: args['email']) end end end end
  24. 45.

    ਧԎ query type QueryType = GraphQL::ObjectType.define do name "Query" description

    "The query root for this schema" field :user do type UserType argument :email, types.String argument :id, types.ID resolve -> (obj, args, ctx) do if args['id'] User.find(args['id']) else User.find_by(email: args['email']) end end end end
  25. 46.

    ਧԎ query type QueryType = GraphQL::ObjectType.define do name "Query" description

    "The query root for this schema" field :user do type UserType argument :email, types.String argument :id, types.ID resolve -> (obj, args, ctx) do if args['id'] User.find(args['id']) else User.find_by(email: args['email']) end end end end
  26. 47.

    ਧԎ query type QueryType = GraphQL::ObjectType.define do name "Query" description

    "The query root for this schema" field :user do type UserType argument :email, types.String argument :id, types.ID resolve -> (obj, args, ctx) do if args['id'] User.find(args['id']) else User.find_by(email: args['email']) end end end end
  27. 48.

    ਧԎ query type QueryType = GraphQL::ObjectType.define do name "Query" description

    "The query root for this schema" field :user do type UserType argument :email, types.String argument :id, types.ID resolve -> (obj, args, ctx) do if args['id'] User.find(args['id']) elsif args[‘email’] User.find_by(email: args['email']) end end end end
  28. 49.

    ਧԎ business objects UserType = GraphQL::ObjectType.define do name 'User' description

    'A user' field :id, !types.ID field :name, types.String, property: :name field :email, types.String, property: :email field :picture, types.Picture, property: :picture end resolve -> (o, a, c) { o.public_send(property) }
  29. 54.
  30. 57.

    Q&A