Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GraphQL on Rails

JunChen Xia
October 12, 2015

GraphQL on Rails

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

JunChen Xia

October 12, 2015
Tweet

More Decks by JunChen Xia

Other Decks in Technology

Transcript

  1. { “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
  2. 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
  3. “The REST interface is designed to be efficient for large-grain

    hypermedia data transfer…” - Dr Roy T Fielding, Author of REST RESTๅᭇአԭय़ᔉଶහഝ࣋ว
  4. { “me”: { “name”: “Junchen Xia”, “picture”: { “height”: 300,

    “width”: 300, “url”: “//image.png” } } } { me { name picture(size: 300) { height width url } } } ىᔮັᧃ
  5. { “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
  6. { “me”: { “name”: “Junchen Xia”, “friends”: [ { “name”:

    “AAA” }, { “name”: “BBB” } ] } } { me { name friends { name } } } one to many
  7. { me { name smallPic: picture(size: 50) { } bigPic:

    picture(size: 300) { } } } fragment pictureParam on picture { height width url } …pictureParam …pictureParam Fragment
  8. च๜༷ஷ { me { name picture { height width url

    } } } query object field object
  9. { me { name picture { height width url }

    } } type Query { me: User user(id: Int): User }
  10. { me { name picture { height width url }

    } } type User { name: String picture(size: Int=50): Picture }
  11. { me { name picture { height width url }

    } } type Picture { height: Int width: Int url: String format: String }
  12. { name(user) { user.name } picture(user, {size}) { user.picture(size) }

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

    } type User { name: String picture(size: Int=50): Picture } Resolver
  14. { name(user) { user.name } picture(user, {size}) { user.picture(size) }

    } type User { name: String picture(size: Int=50): Picture } Resolver
  15. Server Client page data V1 data V1 page data V2

    data V2 page data V3 data V3 V1 V3 V2 GraphQL
  16. Introspection { __schema{ types{ name fields{ name type { name

    } } } } } { "data": { "__schema": { "types": [ { "name": "Query", "fields": [ { "name": "user", "type": { "name": "User" } … }
  17. Ⴒے GraphQL endpoint class GraphqlController < ApplicationController def query render

    json: Schema.execute( params[:query], variables: params[:variables] || {} ) end end
  18. Ⴒے GraphQL endpoint class GraphqlController < ApplicationController def query render

    json: Schema.execute( params[:query], variables: params[:variables] || {} ) end end
  19. ਧԎ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
  20. ਧԎ 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
  21. ਧԎ 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
  22. ਧԎ 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. ਧԎ 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. ਧԎ 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
  25. ਧԎ 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) }
  26. Q&A