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
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
Learning to Love Humans: Emotional Interface Design
aarron
274
40k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.2k
Designing for humans not robots
tammielis
250
25k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
2
290
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
Agile that works and the tools we love
rasmusluckow
328
21k
Gamification - CAS2011
davidbonilla
80
5.1k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
KATA
mclloyd
29
14k
The Language of Interfaces
destraynor
154
24k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
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