roar 0.12.1 → 0.12.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,368 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+
4
+ require 'ostruct'
5
+ require 'roar/representer/json'
6
+
7
+ def reset_representer(*module_name)
8
+ module_name.each do |mod|
9
+ mod.module_eval do
10
+ @representable_attrs = nil
11
+ end
12
+ end
13
+ end
14
+
15
+
16
+ class Song < OpenStruct
17
+ end
18
+
19
+ module SongRepresenter
20
+ include Roar::Representer::JSON
21
+
22
+ property :title
23
+ end
24
+
25
+ song = Song.new(title: "Fate").extend(SongRepresenter)
26
+ puts song.to_json
27
+
28
+ # Parsing
29
+
30
+ song = Song.new.extend(SongRepresenter)
31
+ song.from_json('{"title":"Linoleum"}')
32
+ puts song.title
33
+
34
+
35
+ # Decorator
36
+
37
+ require 'roar/decorator'
38
+
39
+ module Decorator
40
+ class SongRepresenter < Roar::Decorator
41
+ include Roar::Representer::JSON
42
+
43
+ property :title
44
+ end
45
+ end
46
+
47
+ song = Song.new(title: "Medicine Balls")
48
+ puts Decorator::SongRepresenter.new(song).to_json
49
+
50
+ # Collections
51
+
52
+ reset_representer(SongRepresenter)
53
+
54
+ module SongRepresenter
55
+ include Roar::Representer::JSON
56
+
57
+ property :title
58
+ collection :composers
59
+ end
60
+
61
+
62
+ song = Song.new(title: "Roxanne", composers: ["Sting", "Stu Copeland"])
63
+ song.extend(SongRepresenter)
64
+ puts song.to_json
65
+
66
+ # Nesting
67
+
68
+ class Album < OpenStruct
69
+ end
70
+
71
+ module AlbumRepresenter
72
+ include Roar::Representer::JSON
73
+
74
+ property :title
75
+ collection :songs, extend: SongRepresenter, class: Song
76
+ end
77
+
78
+ album = Album.new(title: "True North", songs: [Song.new(title: "The Island"), Song.new(:title => "Changing Tide")])
79
+ album.extend(AlbumRepresenter)
80
+ puts album.to_json
81
+
82
+ album = Album.new
83
+ album.extend(AlbumRepresenter)
84
+
85
+ album.from_json('{"title":"Indestructible","songs":[{"title":"Tropical London"},{"title":"Roadblock"}]}')
86
+
87
+ puts album.songs.last.inspect
88
+
89
+ # Inline Representers # FIXME: what about collections?
90
+
91
+ reset_representer(AlbumRepresenter)
92
+
93
+ module AlbumRepresenter
94
+ include Roar::Representer::JSON
95
+
96
+ property :title
97
+
98
+ collection :songs, class: Song do
99
+ property :title
100
+ end
101
+ end
102
+
103
+ album = Album.new(title: "True North", songs: [Song.new(title: "The Island"), Song.new(:title => "Changing Tide")])
104
+ album.extend(AlbumRepresenter)
105
+ puts album.to_json
106
+
107
+
108
+
109
+ album = Album.new
110
+ album.extend(AlbumRepresenter)
111
+ album.from_json('{"title":"True North","songs":[{"title":"The Island"},{"title":"Changing Tide"}]}')
112
+ puts album.title
113
+ puts album.songs.first.title
114
+
115
+ # parse_strategy: :sync
116
+
117
+ reset_representer(AlbumRepresenter)
118
+
119
+ module AlbumRepresenter
120
+ include Roar::Representer::JSON
121
+
122
+ property :title
123
+
124
+ collection :songs, extend: SongRepresenter, parse_strategy: :sync
125
+ end
126
+
127
+
128
+ album = Album.new(title: "True North", songs: [Song.new(title: "The Island"), Song.new(:title => "Changing Tide")])
129
+ album.extend(AlbumRepresenter)
130
+
131
+ puts album.songs[0].object_id
132
+ album.from_json('{"title":"True North","songs":[{"title":"Secret Society"},{"title":"Changing Tide"}]}')
133
+ puts album.songs[0].title
134
+ puts album.songs[0].object_id##
135
+
136
+ # Coercion, renaming, ..
137
+
138
+ # Hypermedia
139
+
140
+ reset_representer(SongRepresenter)
141
+
142
+ module SongRepresenter
143
+ include Roar::Representer::JSON
144
+ include Roar::Representer::Feature::Hypermedia
145
+
146
+ property :title
147
+
148
+ link :self do
149
+ "http://songs/#{title}"
150
+ end
151
+ end
152
+
153
+ song.extend(SongRepresenter)
154
+ puts song.to_json
155
+
156
+ # roar-rails and URL helpers
157
+
158
+
159
+ # Passing options into link
160
+
161
+ reset_representer(SongRepresenter)
162
+
163
+ module SongRepresenter
164
+ include Roar::Representer::JSON
165
+
166
+ property :title
167
+
168
+ link :self do |opts|
169
+ "http://#{opts[:base_url]}songs/#{title}"
170
+ end
171
+ end
172
+
173
+ song.extend(SongRepresenter)
174
+ puts song.to_json(base_url: "localhost:3001/")
175
+
176
+
177
+ # Discovering Hypermedia
178
+
179
+ song = Song.new.extend(SongRepresenter)
180
+ song.from_json('{"title":"Roxanne","links":[{"rel":"self","href":"http://songs/Roxanne"}]}')
181
+ puts song.links[:self].href
182
+
183
+ # Media Formats: HAL
184
+
185
+ require 'roar/representer/json/hal'
186
+
187
+ module HAL
188
+ module SongRepresenter
189
+ include Roar::Representer::JSON::HAL
190
+
191
+ property :title
192
+
193
+ link :self do
194
+ "http://songs/#{title}"
195
+ end
196
+ end
197
+ end
198
+
199
+ song.extend(HAL::SongRepresenter)
200
+ puts song.to_json
201
+
202
+ reset_representer(AlbumRepresenter)
203
+
204
+ module AlbumRepresenter
205
+ include Roar::Representer::JSON::HAL
206
+
207
+ property :title
208
+
209
+ collection :songs, class: Song, embedded: true do
210
+ property :title
211
+ end
212
+ end
213
+
214
+ album = Album.new(title: "True North", songs: [Song.new(title: "The Island"), Song.new(:title => "Changing Tide")])
215
+ album.extend(AlbumRepresenter)
216
+ puts album.to_json
217
+
218
+ # Media Formats: JSON+Collection
219
+
220
+ require 'roar/representer/json/collection_json'
221
+
222
+
223
+ module Collection
224
+ module SongRepresenter
225
+ include Roar::Representer::JSON::CollectionJSON
226
+ version "1.0"
227
+ href { "http://localhost/songs/" }
228
+
229
+ property :title
230
+
231
+ items(:class => Song) do
232
+ href { "//songs/#{title}" }
233
+
234
+ property :title, :prompt => "Song title"
235
+
236
+ link(:download) { "//songs/#{title}.mp3" }
237
+ end
238
+
239
+ template do
240
+ property :title, :prompt => "Song title"
241
+ end
242
+
243
+ queries do
244
+ link :search do
245
+ {:href => "//search", :data => [{:name => "q", :value => ""}]}
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ song = Song.new(title: "Roxanne")
252
+ song.extend(Collection::SongRepresenter)
253
+ puts song.to_json
254
+
255
+
256
+
257
+ # Client-side
258
+ # share in gem, parse existing document.
259
+
260
+ reset_representer(SongRepresenter)
261
+
262
+ module SongRepresenter
263
+ include Roar::Representer::JSON
264
+ include Roar::Representer::Feature::Hypermedia
265
+
266
+ property :title
267
+ property :id
268
+
269
+ link :self do
270
+ "http://songs/#{title}"
271
+ end
272
+ end
273
+
274
+
275
+ require 'roar/representer/feature/client'
276
+
277
+ module Client
278
+ class Song < OpenStruct
279
+ include Roar::Representer::JSON
280
+ include SongRepresenter
281
+ include Roar::Representer::Feature::Client
282
+ end
283
+ end
284
+
285
+ song = Client::Song.new(title: "Roxanne")
286
+ song.post("http://localhost:4567/songs", "application/json")
287
+ puts song.id
288
+
289
+
290
+ song = Client::Song.new
291
+ song.get("http://localhost:4567/songs/1", "application/json")
292
+ puts song.title
293
+ puts song.links[:self].href
294
+
295
+ # XML
296
+
297
+ require 'roar/representer/xml'
298
+
299
+ module XML
300
+ module SongRepresenter
301
+ include Roar::Representer::XML
302
+ include Roar::Representer::Feature::Hypermedia
303
+
304
+ property :title
305
+ property :id
306
+
307
+ link :self do
308
+ "http://songs/#{title}"
309
+ end
310
+ end
311
+ end
312
+
313
+ song = Song.new(title: "Roxanne", id: 42)
314
+ song.extend(XML::SongRepresenter)
315
+ puts song.to_xml
316
+
317
+ # Coercion
318
+
319
+ reset_representer(SongRepresenter)
320
+
321
+ require 'roar/representer/feature/coercion'
322
+
323
+ module SongRepresenter
324
+ include Roar::Representer::JSON
325
+ include Roar::Representer::Feature::Coercion
326
+
327
+ property :title
328
+ property :released_at, type: DateTime
329
+ end
330
+
331
+ song = Song.new
332
+ song.extend(SongRepresenter)
333
+ song.from_json('{"released_at":"1981/03/31"}')
334
+
335
+ puts song.released_at
336
+
337
+
338
+ class LinkOptionsCollection < Array
339
+
340
+ end
341
+
342
+ module HyperlinkiRepresenter
343
+ include Roar::Representer::JSON
344
+
345
+ def to_hash(*) # setup the link
346
+ # FIXME: why does self.to_s throw a stack level too deep (SystemStackError) ?
347
+ "#{self}"
348
+ # how would the Link instance get access to its Definition in order to execute the block?
349
+ end
350
+ end
351
+
352
+ module Representer
353
+ include Roar::Representer::JSON
354
+
355
+ def self.links
356
+ [:self, :next]
357
+ end
358
+
359
+ collection :links, :extend => HyperlinkiRepresenter
360
+
361
+ def links
362
+ # get link configurations from representable_attrs object.
363
+ #self.representable_attrs.links
364
+ LinkOptionsCollection.new(["self", "next"])
365
+ end
366
+ end
367
+
368
+ puts "".extend(Representer).to_json
@@ -0,0 +1,18 @@
1
+ require "bundler/setup"
2
+ require "sinatra"
3
+ require "ostruct"
4
+ require "roar/representer/json"
5
+
6
+
7
+ get "/method" do
8
+ "<method>get</method>"
9
+ end
10
+
11
+ post "/songs" do
12
+ '{"id":"1","title":"Roxanne","links":[{"rel":"self","href":"http://localhost/songs/1"}]}'
13
+ end
14
+
15
+
16
+ get "/songs/1" do
17
+ '{"id":"1","title":"Roxanne","links":[{"rel":"self","href":"http://localhost/songs/1"}]}'
18
+ end
@@ -18,7 +18,7 @@ module Roar
18
18
  end
19
19
 
20
20
  module InstanceMethods
21
- def to_xml(*args)
21
+ def to_node(*args)
22
22
  before_serialize(*args)
23
23
  super
24
24
  end
@@ -1,3 +1,3 @@
1
1
  module Roar
2
- VERSION = "0.12.1"
2
+ VERSION = "0.12.2"
3
3
  end
@@ -1,10 +1,9 @@
1
1
  require 'test_helper'
2
- require 'roar/representer/feature/hypermedia'
3
- require 'roar/representer/json'
4
2
 
5
3
  class HypermediaTest < MiniTest::Spec
6
4
  describe "Hypermedia Feature" do
7
5
 
6
+ let (:song) { Song.new(:title => "Brandy Wine") }
8
7
 
9
8
  before do
10
9
  @bookmarks = Class.new do
@@ -29,23 +28,65 @@ class HypermediaTest < MiniTest::Spec
29
28
 
30
29
 
31
30
  describe "#to_xml" do
32
- it "sets up links and renders <link> correctly in XML" do
33
- assert_xml_equal '<bookmarks>
34
- <id>1</id>
35
- <link rel="self" href="http://bookmarks"/>
36
- <link rel="all" href="http://bookmarks/all"/>
37
- </bookmarks>', @bookmarks_with_links.new(:id => 1).to_xml
31
+ it "works when no links defined" do
32
+ repr = Module.new do
33
+ include Roar::Representer::XML
34
+ include Roar::Representer::Feature::Hypermedia
35
+
36
+ self.representation_wrap = "song"
37
+ property :title
38
+ end
39
+
40
+ song.extend(repr).to_xml.must_equal_xml "<song><title>Brandy Wine</title></song>"
38
41
  end
39
42
 
40
- it "still works even if there are no links defined" do
41
- assert_xml_equal '<bookmarks/>', @bookmarks.new.to_xml
43
+ let (:rpr) { Module.new do
44
+ include Roar::Representer::XML
45
+ include Roar::Representer::Feature::Hypermedia
46
+
47
+ self.representation_wrap = "song"
48
+ property :title
49
+
50
+ link(:self) { "/songs/#{title}" }
51
+ link(:all) { "/songs" }
52
+ end }
53
+
54
+ it "includes links in rendered document" do
55
+ song.extend(rpr).to_xml.must_equal_xml %{
56
+ <song>
57
+ <title>Brandy Wine</title>
58
+ <link rel="self" href="/songs/Brandy Wine"/>
59
+ <link rel="all" href="/songs"/>
60
+ </song>}
42
61
  end
43
62
 
44
- it "doesn't render links with :links => false" do
45
- assert_xml_equal '<bookmarks>
46
- <id>1</id>
47
- </bookmarks>',
48
- @bookmarks_with_links.new(:id => 1).to_xml(:links => false)
63
+ it "suppresses links when links: false" do
64
+ song.extend(rpr).to_xml(:links => false).must_equal_xml "<song><title>Brandy Wine</title></song>"
65
+ end
66
+
67
+ it "renders nested links" do
68
+ song_rpr = rpr
69
+
70
+ album_rpr = Module.new do
71
+ include Roar::Representer::XML
72
+ include Roar::Representer::Feature::Hypermedia
73
+
74
+ self.representation_wrap = "album"
75
+ collection :songs, :extend => song_rpr
76
+
77
+ link(:self) { "/albums/mixed" }
78
+ end
79
+
80
+ Album.new(:songs => [song]).extend(album_rpr).to_xml.must_equal_xml %{
81
+ <album>
82
+ <song>
83
+ <title>Brandy Wine</title>
84
+ <link rel="self" href="/songs/Brandy Wine"/>
85
+ <link rel="all" href="/songs"/>
86
+ </song>
87
+ <link rel="self" href="/albums/mixed"/>
88
+ </album>
89
+ }
49
90
  end
50
91
  end
51
92
 
@@ -122,7 +163,7 @@ end
122
163
  class LinkCollectionTest < MiniTest::Spec
123
164
  describe "LinkCollection" do
124
165
  subject { Roar::Representer::Feature::Hypermedia::LinkCollection.new }
125
-
166
+
126
167
  describe "#add" do
127
168
  it "keys by using rel string" do
128
169
  subject.size.must_equal 0