Created
March 28, 2018 14:12
-
-
Save phsym/35dab9f880beab9c3afc1053e1d24d0a to your computer and use it in GitHub Desktop.
Coding-Corner 28-03-2018 : Introduction to GraphQL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'graphql' | |
require 'json' | |
require 'sinatra' | |
books = [ | |
{id: 0, title: "A year at the wall", year: 2018, author: 0, themes:["mountains", "swords", "walkers"]}, | |
{id: 1, title: "From basterd to king of the north", year: 2017, author: 0, themes: ["war", "king"]}, | |
{id: 2, title: "Me and my dragons", year: 2017, author: 1, themes: ["dragons"]}, | |
{id: 3, title: "I drink and I know things", year: 2017, author: 3, themes: ["rhum", "wine"]}, | |
{id: 4, title: "How to get hated by the whole world", year: 2015, author: 4, themes: ["war", "king"]} | |
] | |
authors = [ | |
{id: 0, firstname: "John", lastname: "Snow", friends: [1, 2, 3]}, | |
{id: 1, firstname: "Daenerys", lastname: "Targaryen", friends: [0, 3]}, | |
{id: 2, firstname: "Samwell", lastname: "Tarly", friends: [0]}, | |
{id: 3, firstname: "Tyrion", lastname: "Lannister", friends: [0, 1]}, | |
{id: 4, firstname: "Joffrey", lastname: "Baratheon", friends: []}, | |
] | |
Author = GraphQL::ObjectType.define do | |
name "Author" | |
description "A book writer" | |
field :id, !types.Int, "The identification number", hash_key: :id | |
field :firstname, !types.String, "The firstname", hash_key: :firstname | |
field :lastname, !types.String, "The lastname", hash_key: :lastname | |
field :fullname, !types.String, "The fullname", resolve: ->(obj, _, _) { | |
obj[:firstname] + " " + obj[:lastname] | |
} | |
field :Friends, !types[!Author], "List of related authors", resolve: ->(obj, _, _) { | |
authors.select{|a| a[:friends].include?(obj[:id])} | |
} | |
field :Books, !types[!Book], "All the books written", resolve: ->(obj, _, _) { | |
books.select{|b| b[:author] == obj[:id]} | |
} | |
end | |
Book = GraphQL::ObjectType.define do | |
name "Book" | |
description "A book" | |
field :id, !types.Int, "The identification number", hash_key: :id | |
field :title, !types.String, "The book's title", hash_key: :title | |
field :year, !types.Int, "The year of publication", hash_key: :year | |
field :Author, !Author, "Get the book author", resolve: ->(obj, _, _) {authors[obj[:author]]} | |
end | |
QueryType = GraphQL::ObjectType.define do | |
field :Books, !types[!Book], "List all available books", resolve: ->(_, _, _){books} | |
field :Authors, !types[!Author], "List all known book writers", resolve: ->(_, _, _){authors} | |
field :themes, !types[!types.String], "List all book themes", resolve: ->(_, _, _) { | |
books.map{|b| b[:themes]}.reduce([]){|acc, themes| acc + themes}.uniq | |
} | |
field :BooksByTheme do | |
type !types[!Book] | |
description "Search a book by thematic" | |
argument :theme, !types.String, "The theme to look for" | |
resolve ->(_, args, _) { | |
books.select{|b| b[:themes].include?(args[:theme])} | |
} | |
end | |
field :BookById do | |
type Book | |
description "Search a book by its ID" | |
argument :id, !types.Int, "The ID to look for" | |
resolve ->(_, args, _) {books.find{|b| b[:id] == args[:id]}} | |
end | |
field :AuthorByName do | |
type Author | |
description "Search an author by its name" | |
argument :firstname, !types.String, "The firstname to look for" | |
argument :lastname, !types.String, "The lastname to look for" | |
resolve ->(_, args, _) { | |
authors.find{|a| a[:firstname] == args[:firstname] && a[:lastname] == args[:lastname]} | |
} | |
end | |
field :AuthorById do | |
type Author | |
description "Search an author by its ID" | |
argument :id, !types.Int, "The ID to look for" | |
resolve ->(_, args, _) {authors.find{|b| b[:id] == args[:id]}} | |
end | |
end | |
MutationType = GraphQL::ObjectType.define do | |
field :AddAuthor do | |
type !Author | |
argument :firstname, !types.String, "The author's firstname" | |
argument :lastname, !types.String, "The author's lastname" | |
resolve ->(_, args, _) { | |
author = (authors << {id: authors.size, firstname: args[:firstname], lastname: args[:lastname], friends: []}).last | |
# Schema.subscriptions.trigger("AuthorRegistered", {}, author) | |
author | |
} | |
end | |
end | |
# The root of the schema | |
Schema = GraphQL::Schema.define do | |
query QueryType | |
mutation MutationType | |
end | |
# Set the listenning port to 8080 | |
set :port, (ENV['PORT'] || 8080).to_i | |
# Define graphql endpoints | |
post '/graphql' do | |
content_type :json | |
req = JSON.parse(request.body.read) | |
Schema.execute(req['query'], variables: req['variables'], context: {}).to_json | |
end | |
get '/graphql' do | |
content_type :json | |
Schema.execute(params['query'], variables: params['variables'], context: {}).to_json | |
end | |
get '/graphql/idl' do | |
content_type :text | |
Schema.to_definition | |
end | |
# REST interface equivalent | |
get '/authors' do | |
content_type :json | |
authors.to_json | |
end | |
get '/authors/:id' do | |
content_type :json | |
authors[params[:id].to_i].to_json | |
end | |
get '/authors/:id/books' do | |
content_type :json | |
books.select{|b| b[:author] == params[:id].to_i}.to_json | |
end | |
get '/authors/:id/friends' do | |
content_type :json | |
authors.select{|b| b[:friends].include?(params[:id].to_i)}.to_json | |
end | |
get '/books' do | |
content_type :json | |
return books.select{|b| b[:author] == params[:author].to_i}.to_json if params[:author] | |
return books.select{|b| b[:themes].include?(params[:theme])}.to_json if params[:theme] | |
return books.select{|b| b[:year] == params[:year].to_i}.to_json if params[:year] | |
books.to_json | |
end | |
get '/books/:id' do | |
content_type :json | |
books[params[:id].to_i].to_json | |
end | |
get '/books/:id/author' do | |
content_type :json | |
authors.select{|a| a[:id] == books[params[:id].to_i][:author]}.to_json | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is an all in one ruby file definning both graphql and rest interfaces shown during the presentation.
The web GUI code is not part of this (have a look at GraphiQL for more datails)