roar 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9b58dcace50d4224e36f81444ce64ca73dfec11a
4
- data.tar.gz: 419929c85da4aef8a13243364b1c918acfd5312c
3
+ metadata.gz: 9ce6093e4d27114a605b64621c20ab9f5e156266
4
+ data.tar.gz: ac05b9e8989952f88b86caaf2d344a2467f48968
5
5
  SHA512:
6
- metadata.gz: c090f6a70e513ab5ad28155a9c21a453f0e37a289acb2af3a7ade51484d8cc1a76d0c14a02cf6343b054fb9ef2dd392dcae2383b7d219c77e43513d370369c62
7
- data.tar.gz: 3253825814038580793eebb22da120b3af1ce69723d81283b65953e5b30806a91b7627ebb370de30b46440b07b749465ec2db1a9235b884b5de132becf2d4c84
6
+ metadata.gz: 334f83c90798c648945a3d1f0077e503a26f6a51bd2499a3878f48bdb845ad3815a55f8e372078ac28cf5fba628043e7b4edb031625e1abf14ff36dc4fee890d
7
+ data.tar.gz: 329f87d78af5d6e8f214e5dc71a22ff9ce932967bc8bb0e86f5b45ecad6a21eabf546afecd0690ab05dc8e5ccbcfe5f98cfccddc2ddd18f381e6a7ddaf2e441e
@@ -1,3 +1,7 @@
1
+ # 1.0.1
2
+
3
+ * Allow calling `::has_one`, `::links` and `::has_many` in any order in JSON-API. This requires representable >= 2.1.4.
4
+
1
5
  # 1.0.0
2
6
 
3
7
  ## Breakage
data/Gemfile CHANGED
@@ -3,8 +3,8 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in roar.gemspec
4
4
  gemspec
5
5
 
6
- gem "representable", "~> 2.1.0"
7
- # gem "representable", :path => "../representable"
6
+ # gem "representable", "~> 2.1.0"
7
+ gem "representable", :path => "../representable"
8
8
 
9
9
  # as long as this is not merged, i'll vendor the runner file.
10
10
  # gem "sinatra-contrib", :git => "git@github.com:apotonick/sinatra-contrib.git", :branch => "runner"
@@ -8,10 +8,16 @@ Roar is a framework for parsing and rendering REST documents. Nothing more.
8
8
 
9
9
  Representers let you define your API document structure and semantics. They allow both rendering representations from your models _and_ parsing documents to update your Ruby objects. The bi-directional nature of representers make them interesting for both server and client usage.
10
10
 
11
- Roar comes with built-in JSON, JSON-HAL, JSON-API and XML support. Its highly modulare architecture provides features like coercion, hypermedia, HTTP transport, client caching and more.
11
+ Roar comes with built-in JSON, JSON-HAL, JSON-API and XML support. Its highly modular architecture provides features like coercion, hypermedia, HTTP transport, client caching and more.
12
12
 
13
13
  Roar is completely framework-agnostic and loves being used in web kits like Rails, Webmachine, Sinatra, Padrino, etc. If you use Rails, consider [roar-rails](https://github.com/apotonick/roar-rails) for an enjoyable integration.
14
14
 
15
+ <a href="https://leanpub.com/trailblazer">
16
+ ![](https://raw.githubusercontent.com/apotonick/trailblazer/master/doc/trb.jpg)
17
+ </a>
18
+
19
+ Roar is part of the [Trailblazer project](https://github.com/apotonick/trailblazer). Please [buy the book](https://leanpub.com/trailblazer) to support the development. Several chapters will be dedicated to Roar, its integration into operations, hypermedia formats and client-side usage.
20
+
15
21
  ## Representable
16
22
 
17
23
  Roar is just a thin layer on top of the [representable](https://github.com/apotonick/representable) gem. While Roar gives you a DSL and behaviour for creating hypermedia APIs, representable implements all the mapping functionality.
@@ -235,7 +241,7 @@ We're currently [working on](https://github.com/apotonick/roar/issues/85) better
235
241
  Roar provides coercion with the [virtus](https://github.com/solnic/virtus) gem.
236
242
 
237
243
  ```ruby
238
- require 'roar/feature/coercion'
244
+ require 'roar/coercion'
239
245
 
240
246
  module SongRepresenter
241
247
  include Roar::JSON
@@ -280,7 +286,20 @@ module SongRepresenter
280
286
  end
281
287
  ```
282
288
 
283
- The `Hypermedia` feature allows declaring links using the `::link` method.
289
+ The `Hypermedia` feature allows declaring links using the `::link` method. In the block, you have access to the represented model. When using representer modules, the block is executed in the model's context.
290
+
291
+ However, when using decorators, the context is the decorator instance, allowing you to access additional data. Use `represented` to retrieve model data.
292
+
293
+ ```ruby
294
+ class SongRepresenter < Roar::Decorator
295
+ # ..
296
+ link :self do
297
+ "http://songs/#{represented.title}"
298
+ end
299
+ end
300
+ ```
301
+
302
+ This will render links into your representation.
284
303
 
285
304
  ```ruby
286
305
  song.extend(SongRepresenter)
@@ -358,6 +377,8 @@ end
358
377
 
359
378
  Documentation for HAL can be found in the [API docs](http://rdoc.info/github/apotonick/roar/Roar/Representer/JSON/HAL).
360
379
 
380
+ Make sure you [understand the different contexts](#hypermedia) for links when using decorators.
381
+
361
382
  ### Hypermedia
362
383
 
363
384
  Including the `Roar::JSON::HAL` module adds some more DSL methods to your module. It still allows using `::link` but treats them slightly different.
@@ -404,6 +425,8 @@ All HAL features in Roar are discussed in the [API docs](http://rdoc.info/github
404
425
 
405
426
  Roar also supports [JSON-API](http://jsonapi.org/) - yay! It can render _and_ parse singular and collection documents.
406
427
 
428
+ Note that you need representable >= 2.1.4 in your `Gemfile`.
429
+
407
430
  ### Resource
408
431
 
409
432
  A minimal representation can be defined as follows.
@@ -412,7 +435,7 @@ A minimal representation can be defined as follows.
412
435
  require 'roar/json/json_api'
413
436
 
414
437
  module SongsRepresenter
415
- include Roar::JSON::JsonApi
438
+ include Roar::JSON::JSONAPI
416
439
  type :songs
417
440
 
418
441
  property :id
@@ -4,7 +4,7 @@ require 'bundler'
4
4
  Bundler.setup
5
5
 
6
6
  require 'ostruct'
7
- require 'roar/representer/json'
7
+ require 'roar/json'
8
8
 
9
9
  def reset_representer(*module_name)
10
10
  module_name.each do |mod|
@@ -19,12 +19,12 @@ class Song < OpenStruct
19
19
  end
20
20
 
21
21
  module SongRepresenter
22
- include Roar::Representer::JSON
22
+ include Roar::JSON
23
23
 
24
24
  property :title
25
25
  end
26
26
 
27
- song = Song.new(title: "Fate").extend(SongRepresenter)
27
+ song = Song.new(title: 'Fate').extend(SongRepresenter)
28
28
  puts song.to_json
29
29
 
30
30
  # Parsing
@@ -40,13 +40,13 @@ require 'roar/decorator'
40
40
 
41
41
  module Decorator
42
42
  class SongRepresenter < Roar::Decorator
43
- include Roar::Representer::JSON
43
+ include Roar::JSON
44
44
 
45
45
  property :title
46
46
  end
47
47
  end
48
48
 
49
- song = Song.new(title: "Medicine Balls")
49
+ song = Song.new(title: 'Medicine Balls')
50
50
  puts Decorator::SongRepresenter.new(song).to_json
51
51
 
52
52
  # Collections
@@ -54,14 +54,14 @@ puts Decorator::SongRepresenter.new(song).to_json
54
54
  reset_representer(SongRepresenter)
55
55
 
56
56
  module SongRepresenter
57
- include Roar::Representer::JSON
57
+ include Roar::JSON
58
58
 
59
59
  property :title
60
60
  collection :composers
61
61
  end
62
62
 
63
63
 
64
- song = Song.new(title: "Roxanne", composers: ["Sting", "Stu Copeland"])
64
+ song = Song.new(title: 'Roxanne', composers: ['Sting', 'Stu Copeland'])
65
65
  song.extend(SongRepresenter)
66
66
  puts song.to_json
67
67
 
@@ -71,13 +71,13 @@ class Album < OpenStruct
71
71
  end
72
72
 
73
73
  module AlbumRepresenter
74
- include Roar::Representer::JSON
74
+ include Roar::JSON
75
75
 
76
76
  property :title
77
77
  collection :songs, extend: SongRepresenter, class: Song
78
78
  end
79
79
 
80
- album = Album.new(title: "True North", songs: [Song.new(title: "The Island"), Song.new(:title => "Changing Tide")])
80
+ album = Album.new(title: 'True North', songs: [Song.new(title: 'The Island'), Song.new(:title => 'Changing Tide')])
81
81
  album.extend(AlbumRepresenter)
82
82
  puts album.to_json
83
83
 
@@ -88,12 +88,10 @@ album.from_json('{"title":"Indestructible","songs":[{"title":"Tropical London"},
88
88
 
89
89
  puts album.songs.last.inspect
90
90
 
91
- # Inline Representers # FIXME: what about collections?
92
-
93
91
  reset_representer(AlbumRepresenter)
94
92
 
95
93
  module AlbumRepresenter
96
- include Roar::Representer::JSON
94
+ include Roar::JSON
97
95
 
98
96
  property :title
99
97
 
@@ -102,12 +100,10 @@ module AlbumRepresenter
102
100
  end
103
101
  end
104
102
 
105
- album = Album.new(title: "True North", songs: [Song.new(title: "The Island"), Song.new(:title => "Changing Tide")])
103
+ album = Album.new(title: 'True North', songs: [Song.new(title: 'The Island'), Song.new(:title => 'Changing Tide')])
106
104
  album.extend(AlbumRepresenter)
107
105
  puts album.to_json
108
106
 
109
-
110
-
111
107
  album = Album.new
112
108
  album.extend(AlbumRepresenter)
113
109
  album.from_json('{"title":"True North","songs":[{"title":"The Island"},{"title":"Changing Tide"}]}')
@@ -119,7 +115,7 @@ puts album.songs.first.title
119
115
  reset_representer(AlbumRepresenter)
120
116
 
121
117
  module AlbumRepresenter
122
- include Roar::Representer::JSON
118
+ include Roar::JSON
123
119
 
124
120
  property :title
125
121
 
@@ -127,13 +123,13 @@ module AlbumRepresenter
127
123
  end
128
124
 
129
125
 
130
- album = Album.new(title: "True North", songs: [Song.new(title: "The Island"), Song.new(:title => "Changing Tide")])
126
+ album = Album.new(title: 'True North', songs: [Song.new(title: 'The Island'), Song.new(:title => 'Changing Tide')])
131
127
  album.extend(AlbumRepresenter)
132
128
 
133
129
  puts album.songs[0].object_id
134
130
  album.from_json('{"title":"True North","songs":[{"title":"Secret Society"},{"title":"Changing Tide"}]}')
135
131
  puts album.songs[0].title
136
- puts album.songs[0].object_id##
132
+ puts album.songs[0].object_id
137
133
 
138
134
  # Coercion, renaming, ..
139
135
 
@@ -142,8 +138,8 @@ puts album.songs[0].object_id##
142
138
  reset_representer(SongRepresenter)
143
139
 
144
140
  module SongRepresenter
145
- include Roar::Representer::JSON
146
- include Roar::Representer::Feature::Hypermedia
141
+ include Roar::JSON
142
+ include Roar::Hypermedia
147
143
 
148
144
  property :title
149
145
 
@@ -163,7 +159,7 @@ puts song.to_json
163
159
  reset_representer(SongRepresenter)
164
160
 
165
161
  module SongRepresenter
166
- include Roar::Representer::JSON
162
+ include Roar::JSON
167
163
 
168
164
  property :title
169
165
 
@@ -173,7 +169,7 @@ module SongRepresenter
173
169
  end
174
170
 
175
171
  song.extend(SongRepresenter)
176
- puts song.to_json(base_url: "localhost:3001/")
172
+ puts song.to_json(base_url: 'localhost:3001/')
177
173
 
178
174
 
179
175
  # Discovering Hypermedia
@@ -184,11 +180,11 @@ puts song.links[:self].href
184
180
 
185
181
  # Media Formats: HAL
186
182
 
187
- require 'roar/representer/json/hal'
183
+ require 'roar/json/hal'
188
184
 
189
185
  module HAL
190
186
  module SongRepresenter
191
- include Roar::Representer::JSON::HAL
187
+ include Roar::JSON::HAL
192
188
 
193
189
  property :title
194
190
 
@@ -204,7 +200,7 @@ puts song.to_json
204
200
  reset_representer(AlbumRepresenter)
205
201
 
206
202
  module AlbumRepresenter
207
- include Roar::Representer::JSON::HAL
203
+ include Roar::JSON::HAL
208
204
 
209
205
  property :title
210
206
 
@@ -213,57 +209,55 @@ module AlbumRepresenter
213
209
  end
214
210
  end
215
211
 
216
- album = Album.new(title: "True North", songs: [Song.new(title: "The Island"), Song.new(:title => "Changing Tide")])
212
+ album = Album.new(title: 'True North', songs: [Song.new(title: 'The Island'), Song.new(:title => 'Changing Tide')])
217
213
  album.extend(AlbumRepresenter)
218
214
  puts album.to_json
219
215
 
220
216
  # Media Formats: JSON+Collection
221
217
 
222
- require 'roar/representer/json/collection_json'
218
+ require 'roar/json/collection_json'
223
219
 
224
220
 
225
221
  module Collection
226
222
  module SongRepresenter
227
- include Roar::Representer::JSON::CollectionJSON
228
- version "1.0"
229
- href { "http://localhost/songs/" }
223
+ include Roar::JSON::CollectionJSON
224
+ version '1.0'
225
+ href { 'http://localhost/songs/' }
230
226
 
231
227
  property :title
232
228
 
233
229
  items(:class => Song) do
234
230
  href { "//songs/#{title}" }
235
231
 
236
- property :title, :prompt => "Song title"
232
+ property :title, :prompt => 'Song title'
237
233
 
238
234
  link(:download) { "//songs/#{title}.mp3" }
239
235
  end
240
236
 
241
237
  template do
242
- property :title, :prompt => "Song title"
238
+ property :title, :prompt => 'Song title'
243
239
  end
244
240
 
245
241
  queries do
246
242
  link :search do
247
- {:href => "//search", :data => [{:name => "q", :value => ""}]}
243
+ {:href => '//search', :data => [{:name => 'q', :value => ''}]}
248
244
  end
249
245
  end
250
246
  end
251
247
  end
252
248
 
253
- song = Song.new(title: "Roxanne")
249
+ song = Song.new(title: 'Roxanne')
254
250
  song.extend(Collection::SongRepresenter)
255
251
  puts song.to_json
256
252
 
257
-
258
-
259
253
  # Client-side
260
254
  # share in gem, parse existing document.
261
255
 
262
256
  reset_representer(SongRepresenter)
263
257
 
264
258
  module SongRepresenter
265
- include Roar::Representer::JSON
266
- include Roar::Representer::Feature::Hypermedia
259
+ include Roar::JSON
260
+ include Roar::Hypermedia
267
261
 
268
262
  property :title
269
263
  property :id
@@ -274,34 +268,34 @@ module SongRepresenter
274
268
  end
275
269
 
276
270
 
277
- require 'roar/representer/feature/client'
271
+ require 'roar/client'
278
272
 
279
273
  module Client
280
274
  class Song < OpenStruct
281
- include Roar::Representer::JSON
275
+ include Roar::JSON
282
276
  include SongRepresenter
283
- include Roar::Representer::Feature::Client
277
+ include Roar::Client
284
278
  end
285
279
  end
286
280
 
287
- song = Client::Song.new(title: "Roxanne")
288
- song.post("http://localhost:4567/songs", "application/json")
281
+ song = Client::Song.new(title: 'Roxanne')
282
+ song.post(uri: 'http://localhost:4567/songs', as: 'application/json')
289
283
  puts song.id
290
284
 
291
285
 
292
286
  song = Client::Song.new
293
- song.get("http://localhost:4567/songs/1", "application/json")
287
+ song.get(uri: 'http://localhost:4567/songs/1', as: 'application/json')
294
288
  puts song.title
295
289
  puts song.links[:self].href
296
290
 
297
291
  # XML
298
292
 
299
- require 'roar/representer/xml'
293
+ require 'roar/xml'
300
294
 
301
295
  module XML
302
296
  module SongRepresenter
303
- include Roar::Representer::XML
304
- include Roar::Representer::Feature::Hypermedia
297
+ include Roar::XML
298
+ include Roar::Hypermedia
305
299
 
306
300
  property :title
307
301
  property :id
@@ -312,7 +306,7 @@ module XML
312
306
  end
313
307
  end
314
308
 
315
- song = Song.new(title: "Roxanne", id: 42)
309
+ song = Song.new(title: 'Roxanne', id: 42)
316
310
  song.extend(XML::SongRepresenter)
317
311
  puts song.to_xml
318
312
 
@@ -320,11 +314,11 @@ puts song.to_xml
320
314
 
321
315
  reset_representer(SongRepresenter)
322
316
 
323
- require 'roar/representer/feature/coercion'
317
+ require 'roar/coercion'
324
318
 
325
319
  module SongRepresenter
326
- include Roar::Representer::JSON
327
- include Roar::Representer::Feature::Coercion
320
+ include Roar::JSON
321
+ include Roar::Coercion
328
322
 
329
323
  property :title
330
324
  property :released_at, type: DateTime
@@ -342,7 +336,7 @@ class LinkOptionsCollection < Array
342
336
  end
343
337
 
344
338
  module HyperlinkiRepresenter
345
- include Roar::Representer::JSON
339
+ include Roar::JSON
346
340
 
347
341
  def to_hash(*) # setup the link
348
342
  # FIXME: why does self.to_s throw a stack level too deep (SystemStackError) ?
@@ -352,7 +346,7 @@ module HyperlinkiRepresenter
352
346
  end
353
347
 
354
348
  module Representer
355
- include Roar::Representer::JSON
349
+ include Roar::JSON
356
350
 
357
351
  def self.links
358
352
  [:self, :next]
@@ -363,8 +357,8 @@ module Representer
363
357
  def links
364
358
  # get link configurations from representable_attrs object.
365
359
  #self.representable_attrs.links
366
- LinkOptionsCollection.new(["self", "next"])
360
+ LinkOptionsCollection.new(['self', 'next'])
367
361
  end
368
362
  end
369
363
 
370
- puts "".extend(Representer).to_json
364
+ puts ''.extend(Representer).to_json
@@ -2,4 +2,4 @@ source "http://rubygems.org"
2
2
 
3
3
  gemspec path: '../'
4
4
 
5
- gem 'representable', '~> 2.1.3'
5
+ gem 'representable', '~> 2.1.5'
@@ -1,10 +1,12 @@
1
1
  require "roar/http_verbs"
2
2
 
3
3
  module Roar
4
- # Automatically add accessors for properties and collections. Also mixes in HttpVerbs.
4
+
5
+ # Mix in HttpVerbs.
5
6
  module Client
6
7
  include HttpVerbs
7
8
 
9
+ # Add accessors for properties and collections to modules.
8
10
  def self.extended(base)
9
11
  base.instance_eval do
10
12
  representable_attrs.each do |attr|