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
230
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
450
Featured
See All Featured
Bootstrapping a Software Product
garrettdimon
PRO
306
110k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.3k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Build The Right Thing And Hit Your Dates
maggiecrowley
34
2.5k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Why Our Code Smells
bkeepers
PRO
336
57k
KATA
mclloyd
29
14k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
A Philosophy of Restraint
colly
203
16k
A better future with KSS
kneath
238
17k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.1k
Facilitating Awesome Meetings
lara
52
6.2k
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