Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GraphQL on Rails
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Marc-Andre Giroux
September 24, 2016
Programming
400
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GraphQL on Rails
Marc-Andre Giroux
September 24, 2016
More Decks by Marc-Andre Giroux
See All by Marc-Andre Giroux
It Depends - Examining GraphQL Myths & Assumptions
xuorig
0
140
So you Want to Distribute your GraphQL Schema?
xuorig
4
880
So you Want to Distribute your GraphQL Schema?
xuorig
0
690
GraphQL Schema Design @ Scale
xuorig
5
2.2k
Continuous Evolution of GraphQL Schemas @ GitHub
xuorig
3
2.2k
GraphQL à Shopify
xuorig
0
290
Exploring GraphQL
xuorig
0
310
GraphQL @ Shopify
xuorig
6
1.8k
From REST to GraphQL
xuorig
9
1.3k
Other Decks in Programming
See All in Programming
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
120
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
810
OSもどきOS
arkw
0
590
Even G2とAWSで推しのエージェントを召喚しよう!
har1101
1
130
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
14
6.4k
act1-costs.pdf
sumedhbala
0
120
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.5k
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
240
Go1.27で導入されるジェネリクスメソッドでできること
mackee
0
190
Vite+ Unified Toolchain for the Web
naokihaba
0
360
IBM Bobを活用したレガシーアプリの最新化
oniak3ibm
PRO
1
220
Creating Composable Callables in Contemporary C++
rollbear
0
170
Featured
See All Featured
sira's awesome portfolio website redesign presentation
elsirapls
0
290
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
210
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.7k
A designer walks into a library…
pauljervisheath
211
24k
Code Reviewing Like a Champion
maltzj
528
40k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
2.8k
GitHub's CSS Performance
jonrohan
1033
470k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
400
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
870
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
540
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
480
Transcript
GraphQL on Rails Marc-Andre Giroux @__xuorig__
@__xuorig__
@__xuorig__ therakiasite.blogspot.com
@__xuorig__ Montreal, Canada
@__xuorig__
@__xuorig__
@__xuorig__ A simple UI component
@__xuorig__
@__xuorig__ What kind of data is needed?
@__xuorig__ Cart Product ProductImage
@__xuorig__ Reusable endpoints (REST)
@__xuorig__ /carts/1 /products/1 /products/2 /products/3 /product_images/1 /product_images/2 /product_images/3
@__xuorig__ Too many round trips!
@__xuorig__ /carts/1?expand=products
@__xuorig__ /carts/1?fields=products(name, description, price)
@__xuorig__ /carts/1?fields=products/name,description,price
@__xuorig__ Custom Endpoints
@__xuorig__ /cart_with_all_the_stuff_i_need
@__xuorig__
@__xuorig__ /cart_with_all_the_stuff_i_need /cart_version_2_with_all_the_things /cart_with_products_and_images /cart_with_products_and_images_with_price_and_taxes my_tightly_coupled_custom_endpoint_including_only_the_things_i_need_bla_bla_bla_bla /cart_with_products_and_images_with_price_and_taxes_but_no_description /cart_with_products_and_images_with_price_and_taxes_but_no_description_v2
@__xuorig__
@__xuorig__ Server Client Updates a view Creates a new view
New view version Model changes Update endpoints Create new endpoint
@__xuorig__ yo, give me the resource with id = abc
OK, here’s the resource with id = abc Client Server
@__xuorig__ yo, give me the resource v2 with id =
abc OK, here’s the resource v2 with id = abc Client Server
@__xuorig__ yo, give me the resource v3 with id =
abc OK, here’s the resource v3 with id = abc Client Server
@__xuorig__ GraphQL
@__xuorig__ What GraphQL is NOT
@__xuorig__ What GraphQL IS
@__xuorig__ { myShop { name } } Field Selection Set
@__xuorig__ { myShop { name } } Lexed Parsed Validated
Executed { “myShop” { “name”: “GitHub” } }
@__xuorig__ { myShop { name } }
@__xuorig__ { myShop { name } }
@__xuorig__
@__xuorig__ { shop(id: 1) { name } }
@__xuorig__ { myShop { name location { city address }
products(orderby: POPULARITY) { name price } } }
@__xuorig__ { “myShop”: { “name”: “Euruko 2016” “location” { “city”:
“Sofia” “address”: “Av. Diagonal 547” } “products”: [{ “name”: “Conference Ticket” “price”: 500000 }, { “name”: “Cool T-Shirt” “price”: 20000 }] } }
@__xuorig__ Type System
@__xuorig__ { myShop { name location { city address }
products(orderby: POPULARITY) { name price } } }
@__xuorig__ { myShop { name location { city address }
products(orderby: POPULARITY) { name price } } }
@__xuorig__ type QueryRoot { myShop: Shop shop(id: Int): Shop }
@__xuorig__ { myShop { name location { city address }
products(orderby: POPULARITY) { name price } } }
@__xuorig__ type Shop { name: String location: Address products(orderby: OrderEnum):
[Product] } enum ProductOrderEnum { PRICE, POPULARITY, ALPHABETICAL }
@__xuorig__ { myShop { name location { city address }
products(orderby: POPULARITY) { name price } } }
@__xuorig__ type Address { city: String address: String }
@__xuorig__ { myShop { name location { city address }
products(orderby: POPULARITY) { name price } } }
@__xuorig__ type Product { name: String price: Int }
@__xuorig__ { myShop { name yolo { swag } }
}
@__xuorig__ { myShop { name yolo { swag } }
} type Shop { name: String location: Address }
@__xuorig__ Introspection
@__xuorig__ query { __schema { … } }
@__xuorig__ Static Validation Code Generation IDE Integration Auto Documentation
@__xuorig__
@__xuorig__
@__xuorig__ { myShop { name location { city address }
products(orderby: POPULARITY) { id name price } } }
@__xuorig__
@__xuorig__ { myShop { name location { city address }
products(orderby: POPULARITY) { id name price } } }
@__xuorig__ Fragments
@__xuorig__ fragment productFields on Product { id name price }
@__xuorig__ { myShop { name location { city address }
products(orderby: POPULARITY) { ...productFields } } }
@__xuorig__ query Fragment Fragment Fragment Fragment
@__xuorig__ Mutations
@__xuorig__ mutation { createProduct(name: “Nice Mug”, price: 10000) { id
name } }
@__xuorig__ Resolving fields
@__xuorig__ github.com/rmosolgo/graphql-ruby
@__xuorig__ ProductType = GraphQL::ObjectType.define do name "Product" description “A product
sold at a shop” # … end
@__xuorig__ field :name do type types.String resolve -> (obj, args,
ctx) { obj.name } end
@__xuorig__ field :price do type types.Int resolve -> (obj, args,
ctx) do obj.subtotal + obj.taxes + obj.shipping_price end end
@__xuorig__ ShopType = ObjectType.define do name “Shop" description "A Shop"
field :products, [ProductType] end
@__xuorig__ QueryType = ObjectType.define do name “Query" description “The Root
of my Schema" field :myShop, ShopType end
@__xuorig__ MySchema = GraphQL::Schema.new( query: QueryRoot, mutation: MutationRoot )
@__xuorig__ POST /graphql
@__xuorig__ module Api class GraphqlController < ApiController def query query_string
= params[:query] variables = params[:variables] context = { current_user: current_user } # ... end end end
@__xuorig__ module Api class GraphqlController < ApiController def query #
... result = MySchema.query( query_string, variables: variables, context: context ) render json: result end end end
@__xuorig__ Drawbacks and solutions
@__xuorig__ N+1 Queries
@__xuorig__ # Product Type field :image do type ImageType resolve
-> (product, args, ctx) do product.image end end # Shop Type field :products do type [ProductType] resolve -> (shop, args, ctx) do shop.products end end
@__xuorig__ Product Load (1.0ms) SELECT "products".* FROM "products" WHERE "products"."shop_id"
= … Image Load (0.9ms) SELECT "images".* FROM "images" WHERE "images"."product_id" = … Image Load (0.2ms) SELECT "images".* FROM "images" WHERE "images"."product_id" = … Image Load (0.1ms) SELECT "images".* FROM "images" WHERE "images"."product_id" = …
@__xuorig__ Solution: Batching + Caching
@__xuorig__ field :image do type ImageType resolve -> (product, args,
ctx) do RecordLoader.for(Image).load(product.image_id) end end
@__xuorig__ HTTP Caching
@__xuorig__ Solution: Client Side Cache
@__xuorig__ Normalized Cache
@__xuorig__ query { shop { products { price } }
} query { shop { product(id: 1) { price } } }
@__xuorig__ { root: { shop: { products: [ Link.new(1) ]
} }, 1: { price: 1000 } }
@__xuorig__ https://github.com/facebook/relay http://www.apollostack.com/
@__xuorig__ Security
@__xuorig__ Query Depth Timeouts Query Complexity
@__xuorig__ Future
@__xuorig__ Subscriptions
@__xuorig__ subscription { productInventorySubscribe { products { inventory } }
}
@__xuorig__ Deferred Queries
@__xuorig__ query { shop { name description products { name
price } } }
@__xuorig__ query { shop { name description products { name
price } } }
@__xuorig__ query { shop { name description products @defer {
name price } } }
@__xuorig__
@__xuorig__ yo, give me the resource with id = abc
OK, here’s the resource with id = abc Client Server
@__xuorig__ Client Server yo, give me the resource with id
= 1 yo, give me the resource with id = 2 yo, give me the resource with id = 3 yo, give me the resource with id = 4
@__xuorig__ oh boy :( Client Server
@__xuorig__ I need that exact data shape (requirements) Here is
everything you can do! (capabilities) Client Server
@__xuorig__ Efficiency
@__xuorig__ Predictability
@__xuorig__ Thank you! Marc-Andre Giroux @__xuorig__