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
Hypermedia For Y'All
Search
apotonick
December 27, 2011
0
220
Hypermedia For Y'All
The presentation I gave at the RubyConf Brazil 2011.
apotonick
December 27, 2011
Tweet
Share
More Decks by apotonick
See All by apotonick
Off The Tracks
apotonick
4
130
Sexy Time with Nick Sutterer
apotonick
1
440
Featured
See All Featured
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
KATA
mclloyd
29
14k
Facilitating Awesome Meetings
lara
50
6.1k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Unsuck your backbone
ammeep
669
57k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
26
1.9k
We Have a Design System, Now What?
morganepeng
51
7.3k
The Pragmatic Product Professional
lauravandoore
32
6.3k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.7k
How to train your dragon (web standard)
notwaldorf
88
5.7k
GraphQLとの向き合い方2022年版
quramy
44
13k
Transcript
Roar! Nick „The German“ Sutterer @apotonick Hypermedia for y'all! The
Missing Ingredient in REST
2 Roar! 43.8 minutes... REST Representations Hypermedia Roooaaar
3 Roar! REST?
4 Roar! „architectural style for distributed hypermedia systems“ Roy Fielding's
dissertation, chapter 5, line 1
5 Roar! require 'rest' class Application include Restful end
6 Roar! GET http://nick/state {„status“ : „sober“}
Roar! Resource Unique URL http://beer/rocky Uniform Interface GET POST PUT
... Represen- tation
Roar! „REST“ monolithic app pretty URLs GET renders models (JSON/HTML)
POST to create and update models
Roar! Mono- lithic Systems
Roar! componentized app ...still pretty URLs real REST services with
GET, PUT, POST, DELETE no HTML! embedded hypermedia REST
Roar! Split it!
Roar! BURP! Order!
Roar! BURP! Beer shop system Using RESTful backend services and
a separate Presentation layer !
Roar! A typical REST session!
Roar! GET/PUT/ http://... ------------------- <document> ------------------- <document>
Roar! GET http://beers/1 name: Rocky alc : 6.0
Roar! POST http://beers/ ------------------- name: Beck's alc : 5.1 Created!
It's at http://beers/becks
18 Roar! GET: show POST: create PUT: update ... REST
is
19 Roar! CRUD is not REST!
Roar! A hypermedia- driven REST session!
Roar! BURP! Order!
Roar! BURP! REST Service Client
23 Roar! BURP!
24 Roar! BURP!
Roar! GET http://orders/1 id: 1 created_at: August 30 to proceed:
http://orders/1/pay to update: http://orders/1
Roar! to proceed: http://orders/1/pay to update: http://orders/1 „ HATEOAS“ WTF?
Roar! „HATEOAS“ - embedd actions that make sense in current
application state
Roar! {order: { id : 1 created_at: August 31 links
: [ {rel : proceed href: http://orders/1/pay} {rel : self href: http://orders/1} ] } Hypermedia & JSON
Roar! rel : proceed href: http://orders/1/pay
30 Roar! <link rel =„proceed“ href =„http://orders/1/pay“ />
Roar! rel – link semantic, „meaning“ href – resource URL
Roar! Creating a new order
Roar! POST http://orders ------------------------ client_id: 42 id : 1 client_id:
42 beers : [] links : [ {rel : self href: http://orders/1} {rel : beers href: http://orders/1/be ]
Roar! Single entry point – the one and only URL
we know POST http://orders ------------------------ client_id: 42
Roar! id : 1 client_id: 42 beers : [] links
: [ {rel: self href: http://orders/1} {rel: beers href: http://orders/1/beers} ] self link – pointing to current resource
Roar! id : 1 client_id: 42 beers : [] links
: [ {rel: self href: http://orders/1} {rel: beers href: http://orders/1/beers} ] beers link – items placed in order
Roar! GET the new order
Roar! GET http://orders/1 id : 1 client_id: 42 beers :
[] links : [ {rel : self href: http://orders/1} {rel : beers href: http://orders/1/be ]
Roar! Follow the beers link
Roar! GET http://orders/1/beers beers: [] links: [ {rel : self
href: http://orders/1/be {rel : order href: http://orders/1}
Roar! Add beer to order
Roar! POST http://orders/1/beers ------------------------ {name: Anchor Steam} Created! It's at
http://orders/1/beers/anchors team Created! It's at http://orders/1/beers/anchors team
Roar! Reloading the order
Roar! GET http://orders/1 id : 1 client_id: 42 beers: [
{name: Anchor Steam links: [ {rel : self href: http://orders/1/ ]} ],
Roar! id : 1 client_id: 42 beers: [ {name: Anchor
Steam links: [ {rel : self href: http://orders/1/beers/anchorsteam} ]} ], links: [ {rel: self href: http://orders/1} {rel: beers href: http://orders/1/beers} ] +
Roar! id : 1 client_id: 42 beers: [ {name: Anchor
Steam links: [ {rel : self href: http://orders/1/beers/anchorsteam} ]} ], links: [ {rel: self href: http://orders/1} {rel: beers href: http://orders/1/beers} ] +
Roar! +
Roar! Removing beer from order
Roar! DELETE http://orders/1/beers/anchorsteam +
Roar! Reloading the order
Roar! GET http://orders/1 id : 1 client_id: 42 beers :
[] links : [ {rel : self href: http://orders/1} {rel : beers href: http://orders/1/be ]
Roar! GET http://orders/1 id : 1 client_id: 42 beers :
[] links : [ {rel : self href: http://orders/1} {rel : beers href: http://orders/1/be ]
53 Roar! http://orders/ POST GET GET + DELETE ? GET
POST
54 Roar! What we didn't do... PUT http://orders/1 DELETE http://orders/1/items
...
55 Roar! Code!
Roar! Roar!
gem 'roar'
58 Roar! class Beer include Roar::Representer::JSON property :name property :id
link :self do beer_url(id) end Plain properties Hypermedia support yo
59 Roar! Beer.new(:id => 1, :name => "NickBrew").to_json from Roar
{"beer":{ "id" : 1, "name" : "NickBrew", "links": [{"rel":"self","href":"http://beers/1"}]}}
60 Roar! brew = Beer.from_json '{"beer":{ "id" : 1, "name"
: "NickBrew"}}' from Roar brew.name #=> „NickBrew“
61 Roar! class Beer include Roar::Representer::XML ... jaja brew.to_xml <beer>
<id>1</id> <name>NickBrew</name> <link rel="self" href="http://beers/1"/> </beer>
62 Roar! class Order include Roar::Representer::JSON collection Beer
63 Roar! class Collection include Roar::Representer::JSON link :next do page_url(page)
end end class Beers < Collection collection Beer
64 Roar! brew.new(:name => „SKOL“) brew.new(:name => „SKOL“) brew.extend Feature::HTTPVerbs
brew.new(:name => „SKOL“) brew.extend Feature::HTTPVerbs brew.post!(„http://beers“) brew.new(:name => „SKOL“) brew.extend Feature::HTTPVerbs brew.post!(„http://beers“) puts „I'm at“ + brew.links[:self] #=> „http://beers/99“
65 Roar!
66 Roar! „REST APIs must be hypertext-driven“: http://roy.gbiv.com/untangled/2008/rest-apis-must-be- hypertext-driven REST
in Practice – O'REILLY RESTful Web Services Cookbook – O'REILLY
67 Roar! Are you local?
Roar! Thirsty? http://github.com/apotonick/roar @apotonick