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.
@@ -22,7 +22,7 @@ module Roar
22
22
  singular = self # e.g. Song::Representer
23
23
 
24
24
  # this basically does Module.new { include Hash::Collection .. }
25
- build_inline(nil, [Document::Collection, Representable::Hash::Collection, Roar::JSON], "", {}) do
25
+ build_inline(nil, [Representable::Hash::Collection, Document::Collection, Roar::JSON], "", {}) do
26
26
  items extend: singular, :parse_strategy => :sync
27
27
 
28
28
  representable_attrs[:resource_representer] = singular.representable_attrs[:resource_representer]
@@ -36,7 +36,7 @@ module Roar
36
36
  module Singular
37
37
  def to_hash(options={})
38
38
  # per resource:
39
- super(:exclude => [:links]).tap do |hash|
39
+ super(options.merge(:exclude => [:links])).tap do |hash|
40
40
  hash["links"] = hash.delete("_links") if hash["_links"]
41
41
  end
42
42
  end
@@ -81,7 +81,7 @@ module Roar
81
81
 
82
82
  # Per-model links.
83
83
  def links(&block)
84
- nested(:_links, &block)
84
+ nested(:_links, :inherit => true, &block)
85
85
  end
86
86
 
87
87
  # TODO: always create _links.
@@ -1,3 +1,3 @@
1
1
  module Roar
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.authors = ["Nick Sutterer"]
9
9
  s.email = ["apotonick@gmail.com"]
10
10
  s.homepage = "http://rubygems.org/gems/roar"
11
- s.summary = %q{Resource-oriented architectures in Ruby.}
12
- s.description = %q{Streamlines the development of RESTful, resource-oriented architectures in Ruby.}
11
+ s.summary = %q{Parse and render REST API documents using representers.}
12
+ s.description = %q{Object-oriented representers help you defining nested REST API documents which can then be rendered and parsed using one and the same concept.}
13
13
  s.license = 'MIT'
14
14
 
15
15
  s.files = `git ls-files`.split("\n")
@@ -0,0 +1,64 @@
1
+ require 'test_helper'
2
+ require 'roar/decorator'
3
+ require 'roar/client'
4
+
5
+ class DecoratorClientTest < MiniTest::Spec
6
+ class Crew
7
+ attr_accessor :moniker, :company
8
+ end
9
+
10
+ class CrewDecorator < Roar::Decorator
11
+ include Roar::JSON
12
+ include Roar::Hypermedia
13
+
14
+ property :moniker, as: :name
15
+ property :company, as: :label
16
+
17
+ link(:self) do
18
+ "http://bands/#{represented.moniker}"
19
+ end
20
+ end
21
+
22
+ class CrewClient < CrewDecorator
23
+ include Roar::Client
24
+ end
25
+
26
+ before do
27
+ @crew = Crew.new
28
+ @client = CrewClient.new(@crew)
29
+ end
30
+
31
+ describe 'HttpVerbs integration' do
32
+ describe '#get' do
33
+ it 'updates instance with incoming representation' do
34
+ @client.get(uri: 'http://localhost:4567/bands/slayer', as: 'application/json')
35
+ @crew.moniker.must_equal 'Slayer'
36
+ @crew.company.must_equal 'Canadian Maple'
37
+ end
38
+ end
39
+
40
+ describe '#post' do
41
+ it 'creates a new resource with the given values' do
42
+ @crew.moniker = 'Strung Out'
43
+ @crew.company.must_be_nil
44
+
45
+ @client.post(uri: 'http://localhost:4567/bands', as: 'application/xml')
46
+ @crew.moniker.must_equal 'STRUNG OUT'
47
+ @crew.company.must_be_nil
48
+ end
49
+ end
50
+ end
51
+
52
+ describe '#to_hash' do
53
+ it 'suppresses rendering links' do
54
+ @crew.moniker = 'Silence'
55
+ @client.to_json.must_equal %{{\"name\":\"Silence\",\"links\":[]}}
56
+ end
57
+
58
+ # since this is considered dangerous, we test the mutuable options.
59
+ it "adds links: false to options" do
60
+ @client.to_hash(options = {})
61
+ options.must_equal({:links => false})
62
+ end
63
+ end
64
+ end
@@ -2,394 +2,409 @@ require 'test_helper'
2
2
  require 'roar/json/json_api'
3
3
  require 'json'
4
4
 
5
- class JSONAPITest < MiniTest::Spec
6
- let(:song) {
7
- s = OpenStruct.new(
8
- bla: "halo",
9
- id: "1",
10
- title: 'Computadores Fazem Arte',
11
- album: OpenStruct.new(id: 9, title: "Hackers"),
12
- :album_id => "9",
13
- :musician_ids => ["1","2"],
14
- :composer_id => "10",
15
- :listener_ids => ["8"],
16
- musicians: [OpenStruct.new(id: 1, name: "Eddie Van Halen"), OpenStruct.new(id: 2, name: "Greg Howe")]
17
- )
18
-
19
- }
20
-
21
- # minimal resource, singular
22
- module MinimalSingular
23
- include Roar::JSON::JSONAPI
24
- type :songs
25
-
26
- property :id
27
- end
28
-
29
- class MinimalSingularDecorator < Roar::Decorator
30
- include Roar::JSON::JSONAPI
31
- type :songs
5
+ require "representable/version"
6
+ if Gem::Version.new(Representable::VERSION) >= Gem::Version.new("2.1.4") # TODO: remove check once we bump representable dependency.
7
+ class JSONAPITest < MiniTest::Spec
8
+ let(:song) {
9
+ s = OpenStruct.new(
10
+ bla: "halo",
11
+ id: "1",
12
+ title: 'Computadores Fazem Arte',
13
+ album: OpenStruct.new(id: 9, title: "Hackers"),
14
+ :album_id => "9",
15
+ :musician_ids => ["1","2"],
16
+ :composer_id => "10",
17
+ :listener_ids => ["8"],
18
+ musicians: [OpenStruct.new(id: 1, name: "Eddie Van Halen"), OpenStruct.new(id: 2, name: "Greg Howe")]
19
+ )
32
20
 
33
- property :id
34
- end
21
+ }
35
22
 
36
- [MinimalSingular, MinimalSingularDecorator].each do |representer|
37
- describe "minimal singular with #{representer}" do
38
- subject { representer.prepare(song) }
23
+ # minimal resource, singular
24
+ module MinimalSingular
25
+ include Roar::JSON::JSONAPI
26
+ type :songs
39
27
 
40
- it { subject.to_json.must_equal "{\"songs\":{\"id\":\"1\"}}" }
41
- it { subject.from_json("{\"songs\":{\"id\":\"2\"}}").id.must_equal "2" }
28
+ property :id
42
29
  end
43
- end
44
-
45
30
 
31
+ class MinimalSingularDecorator < Roar::Decorator
32
+ include Roar::JSON::JSONAPI
33
+ type :songs
46
34
 
47
- module Singular
48
- include Roar::JSON::JSONAPI
49
- type :songs
35
+ property :id
36
+ end
50
37
 
51
- property :id
52
- property :title
38
+ [MinimalSingular, MinimalSingularDecorator].each do |representer|
39
+ describe "minimal singular with #{representer}" do
40
+ subject { representer.prepare(song) }
53
41
 
54
- # local per-model "id" links
55
- links do
56
- property :album_id, :as => :album
57
- collection :musician_ids, :as => :musicians
42
+ it { subject.to_json.must_equal "{\"songs\":{\"id\":\"1\"}}" }
43
+ it { subject.from_json("{\"songs\":{\"id\":\"2\"}}").id.must_equal "2" }
44
+ end
58
45
  end
59
- has_one :composer
60
- has_many :listeners
61
46
 
47
+ module Singular
48
+ include Roar::JSON::JSONAPI
49
+ type :songs
62
50
 
63
- # global document links.
64
- link "songs.album" do
65
- {
66
- type: "album",
67
- href: "http://example.com/albums/{songs.album}"
68
- }
69
- end
51
+ property :id
52
+ property :title, if: lambda { |args| args[:omit_title] != true }
70
53
 
71
- compound do
72
- property :album do
73
- property :title
54
+ # local per-model "id" links
55
+ links do
56
+ property :album_id, :as => :album
57
+ collection :musician_ids, :as => :musicians
74
58
  end
59
+ has_one :composer
60
+ has_many :listeners
75
61
 
76
- collection :musicians do
77
- property :name
78
- end
79
- end
80
- end
81
62
 
82
- class SingularDecorator < Roar::Decorator
83
- include Roar::JSON::JSONAPI
84
- type :songs
63
+ # global document links.
64
+ link "songs.album" do
65
+ {
66
+ type: "album",
67
+ href: "http://example.com/albums/{songs.album}"
68
+ }
69
+ end
85
70
 
86
- property :id
87
- property :title
71
+ compound do
72
+ property :album do
73
+ property :title
74
+ end
88
75
 
89
- # local per-model "id" links
90
- links do
91
- property :album_id, :as => :album
92
- collection :musician_ids, :as => :musicians
76
+ collection :musicians do
77
+ property :name
78
+ end
79
+ end
93
80
  end
94
- has_one :composer
95
- has_many :listeners
96
81
 
82
+ class SingularDecorator < Roar::Decorator
83
+ include Roar::JSON::JSONAPI
84
+ type :songs
97
85
 
98
- # global document links.
99
- link "songs.album" do
100
- {
101
- type: "album",
102
- href: "http://example.com/albums/{songs.album}"
103
- }
104
- end
105
-
106
- compound do
107
- property :album do
108
- property :title
109
- end
86
+ property :id
87
+ property :title, if: lambda { |args| args[:omit_title] != true }
110
88
 
111
- collection :musicians do
112
- property :name
89
+ # NOTE: it is important to call has_one, then links, then has_many to assert that they all write
90
+ #to the same _links property and do NOT override things.
91
+ has_one :composer
92
+ # local per-model "id" links
93
+ links do
94
+ property :album_id, :as => :album
95
+ collection :musician_ids, :as => :musicians
113
96
  end
114
- end
115
- end
97
+ has_many :listeners
116
98
 
117
- [Singular, SingularDecorator].each do |representer|
118
- describe "singular with #{representer}" do
119
- subject { song.extend(Singular) }
120
99
 
121
- let (:document) do
100
+ # global document links.
101
+ link "songs.album" do
122
102
  {
123
- "songs" => {
124
- "id" => "1",
125
- "title" => "Computadores Fazem Arte",
126
- "links" => {
127
- "album" => "9",
128
- "musicians" => [ "1", "2" ],
129
- "composer"=>"10",
130
- "listeners"=>["8"]
131
- }
132
- },
133
- "links" => {
134
- "songs.album"=> {
135
- "href"=>"http://example.com/albums/{songs.album}", "type"=>"album"
136
- }
137
- },
138
- "linked" => {
139
- "album"=> [{"title"=>"Hackers"}],
140
- "musicians"=> [
141
- {"name"=>"Eddie Van Halen"},
142
- {"name"=>"Greg Howe"}
143
- ]
144
- }
103
+ type: "album",
104
+ href: "http://example.com/albums/{songs.album}"
145
105
  }
146
106
  end
147
107
 
148
- # to_hash
149
- it do
150
- subject.to_hash.must_equal document
151
- end
108
+ compound do
109
+ property :album do
110
+ property :title
111
+ end
152
112
 
153
- # #to_json
154
- it do
155
- subject.to_json.must_equal JSON.generate(document)
156
- end
157
-
158
- # #from_json
159
- it do
160
- song = OpenStruct.new.extend(Singular)
161
- song.from_json(
162
- JSON.generate(
163
- {
164
- "songs" => {
165
- "id" => "1",
166
- "title" => "Computadores Fazem Arte",
167
- "links" => {
168
- "album" => "9",
169
- "musicians" => [ "1", "2" ],
170
- "composer"=>"10",
171
- "listeners"=>["8"]
172
- }
173
- },
174
- "links" => {
175
- "songs.album"=> {
176
- "href"=>"http://example.com/albums/{songs.album}", "type"=>"album"
177
- }
178
- }
179
- }
180
- )
181
- )
182
-
183
- song.id.must_equal "1"
184
- song.title.must_equal "Computadores Fazem Arte"
185
- song.album_id.must_equal "9"
186
- song.musician_ids.must_equal ["1", "2"]
187
- song.composer_id.must_equal "10"
188
- song.listener_ids.must_equal ["8"]
113
+ collection :musicians do
114
+ property :name
115
+ end
189
116
  end
190
117
  end
191
- end
192
-
193
118
 
194
- # collection with links
195
- [Singular, SingularDecorator].each do |representer|
196
- describe "collection with links and compound" do
197
- subject { Singular.for_collection.prepare([song, song]) }
119
+ [Singular, SingularDecorator].each do |representer|
120
+ describe "singular with #{representer}" do
121
+ subject { song.extend(Singular) }
198
122
 
199
- let (:document) do
200
- {
201
- "songs" => [
202
- {
123
+ let (:document) do
124
+ {
125
+ "songs" => {
203
126
  "id" => "1",
204
127
  "title" => "Computadores Fazem Arte",
205
128
  "links" => {
206
129
  "album" => "9",
207
130
  "musicians" => [ "1", "2" ],
208
131
  "composer"=>"10",
209
- "listeners"=>["8"]
132
+ "listeners"=>["8"]
210
133
  }
211
- }, {
212
- "id" => "1",
213
- "title" => "Computadores Fazem Arte",
214
- "links" => {
215
- "album" => "9",
216
- "musicians" => [ "1", "2" ],
217
- "composer"=>"10",
218
- "listeners"=>["8"]
134
+ },
135
+ "links" => {
136
+ "songs.album"=> {
137
+ "href"=>"http://example.com/albums/{songs.album}", "type"=>"album"
219
138
  }
220
- }
221
- ],
222
- "links" => {
223
- "songs.album" => {
224
- "href" => "http://example.com/albums/{songs.album}",
225
- "type" => "album" # DISCUSS: does that have to be albums ?
226
139
  },
227
- },
228
- "linked"=>{
229
- "album" =>[{"title"=>"Hackers"}], # only once!
230
- "musicians"=>[{"name"=>"Eddie Van Halen"}, {"name"=>"Greg Howe"}]
140
+ "linked" => {
141
+ "album"=> [{"title"=>"Hackers"}],
142
+ "musicians"=> [
143
+ {"name"=>"Eddie Van Halen"},
144
+ {"name"=>"Greg Howe"}
145
+ ]
146
+ }
231
147
  }
232
- }
233
- end
148
+ end
149
+
150
+ # to_hash
151
+ it do
152
+ subject.to_hash.must_equal document
153
+ end
154
+
155
+ # to_hash(options)
156
+ it do
157
+ subject.to_hash(omit_title: true)['songs'].wont_include('title')
158
+ end
159
+
160
+ # #to_json
161
+ it do
162
+ subject.to_json.must_equal JSON.generate(document)
163
+ end
164
+
165
+ # #from_json
166
+ it do
167
+ song = OpenStruct.new.extend(Singular)
168
+ song.from_json(
169
+ JSON.generate(
170
+ {
171
+ "songs" => {
172
+ "id" => "1",
173
+ "title" => "Computadores Fazem Arte",
174
+ "links" => {
175
+ "album" => "9",
176
+ "musicians" => [ "1", "2" ],
177
+ "composer"=>"10",
178
+ "listeners"=>["8"]
179
+ }
180
+ },
181
+ "links" => {
182
+ "songs.album"=> {
183
+ "href"=>"http://example.com/albums/{songs.album}", "type"=>"album"
184
+ }
185
+ }
186
+ }
187
+ )
188
+ )
234
189
 
235
- # to_hash
236
- it do
237
- subject.to_hash.must_equal document
190
+ song.id.must_equal "1"
191
+ song.title.must_equal "Computadores Fazem Arte"
192
+ song.album_id.must_equal "9"
193
+ song.musician_ids.must_equal ["1", "2"]
194
+ song.composer_id.must_equal "10"
195
+ song.listener_ids.must_equal ["8"]
196
+ end
238
197
  end
239
-
240
- # #to_json
241
- it { subject.to_json.must_equal JSON.generate(document) }
242
198
  end
243
199
 
244
200
 
245
- # from_json
246
- it do
247
- song1, song2 = Singular.for_collection.prepare([OpenStruct.new, OpenStruct.new]).from_json(
248
- JSON.generate(
201
+ # collection with links
202
+ [Singular, SingularDecorator].each do |representer|
203
+ describe "collection with links and compound with #{representer}" do
204
+ subject { representer.for_collection.prepare([song, song]) }
205
+
206
+ let (:document) do
249
207
  {
250
208
  "songs" => [
251
209
  {
252
210
  "id" => "1",
253
211
  "title" => "Computadores Fazem Arte",
254
212
  "links" => {
213
+ "composer"=>"10",
255
214
  "album" => "9",
256
215
  "musicians" => [ "1", "2" ],
257
- "composer"=>"10",
258
216
  "listeners"=>["8"]
259
- },
260
- },
261
- {
262
- "id" => "2",
263
- "title" => "Talking To Remind Me",
217
+ }
218
+ }, {
219
+ "id" => "1",
220
+ "title" => "Computadores Fazem Arte",
264
221
  "links" => {
265
- "album" => "1",
266
- "musicians" => [ "3", "4" ],
267
- "composer"=>"2",
268
- "listeners"=>["6"]
222
+ "composer"=>"10",
223
+ "album" => "9",
224
+ "musicians" => [ "1", "2" ],
225
+ "listeners"=>["8"]
269
226
  }
270
- },
227
+ }
271
228
  ],
272
229
  "links" => {
273
- "songs.album"=> {
274
- "href"=>"http://example.com/albums/{songs.album}", "type"=>"album"
275
- }
230
+ "songs.album" => {
231
+ "href" => "http://example.com/albums/{songs.album}",
232
+ "type" => "album" # DISCUSS: does that have to be albums ?
233
+ },
234
+ },
235
+ "linked"=>{
236
+ "album" =>[{"title"=>"Hackers"}], # only once!
237
+ "musicians"=>[{"name"=>"Eddie Van Halen"}, {"name"=>"Greg Howe"}]
276
238
  }
277
239
  }
240
+ end
241
+
242
+ # to_hash
243
+ it do
244
+ subject.to_hash.must_equal document
245
+ end
246
+
247
+ # to_hash(options)
248
+ it do
249
+ subject.to_hash(omit_title: true)['songs'].each do |song|
250
+ song.wont_include('title')
251
+ end
252
+ end
253
+
254
+ # #to_json
255
+ it { subject.to_json.must_match /linked/ } # hash ordering changes, and i don't care why.
256
+ end
257
+
258
+
259
+ # from_json
260
+ it do
261
+ song1, song2 = Singular.for_collection.prepare([OpenStruct.new, OpenStruct.new]).from_json(
262
+ JSON.generate(
263
+ {
264
+ "songs" => [
265
+ {
266
+ "id" => "1",
267
+ "title" => "Computadores Fazem Arte",
268
+ "links" => {
269
+ "album" => "9",
270
+ "musicians" => [ "1", "2" ],
271
+ "composer"=>"10",
272
+ "listeners"=>["8"]
273
+ },
274
+ },
275
+ {
276
+ "id" => "2",
277
+ "title" => "Talking To Remind Me",
278
+ "links" => {
279
+ "album" => "1",
280
+ "musicians" => [ "3", "4" ],
281
+ "composer"=>"2",
282
+ "listeners"=>["6"]
283
+ }
284
+ },
285
+ ],
286
+ "links" => {
287
+ "songs.album"=> {
288
+ "href"=>"http://example.com/albums/{songs.album}", "type"=>"album"
289
+ }
290
+ }
291
+ }
292
+ )
278
293
  )
279
- )
280
294
 
281
- song1.id.must_equal "1"
282
- song1.title.must_equal "Computadores Fazem Arte"
283
- song1.album_id.must_equal "9"
284
- song1.musician_ids.must_equal ["1", "2"]
285
- song1.composer_id.must_equal "10"
286
- song1.listener_ids.must_equal ["8"]
287
-
288
- song2.id.must_equal "2"
289
- song2.title.must_equal "Talking To Remind Me"
290
- song2.album_id.must_equal "1"
291
- song2.musician_ids.must_equal ["3", "4"]
292
- song2.composer_id.must_equal "2"
293
- song2.listener_ids.must_equal ["6"]
295
+ song1.id.must_equal "1"
296
+ song1.title.must_equal "Computadores Fazem Arte"
297
+ song1.album_id.must_equal "9"
298
+ song1.musician_ids.must_equal ["1", "2"]
299
+ song1.composer_id.must_equal "10"
300
+ song1.listener_ids.must_equal ["8"]
301
+
302
+ song2.id.must_equal "2"
303
+ song2.title.must_equal "Talking To Remind Me"
304
+ song2.album_id.must_equal "1"
305
+ song2.musician_ids.must_equal ["3", "4"]
306
+ song2.composer_id.must_equal "2"
307
+ song2.listener_ids.must_equal ["6"]
308
+ end
294
309
  end
295
- end
296
310
 
297
311
 
298
- class CollectionWithoutCompound < self
299
- module Representer
300
- include Roar::JSON::JSONAPI
301
- type :songs
312
+ class CollectionWithoutCompound < self
313
+ module Representer
314
+ include Roar::JSON::JSONAPI
315
+ type :songs
302
316
 
303
- property :id
304
- property :title
317
+ property :id
318
+ property :title
305
319
 
306
- # local per-model "id" links
307
- links do
308
- property :album_id, :as => :album
309
- collection :musician_ids, :as => :musicians
310
- end
311
- has_one :composer
312
- has_many :listeners
320
+ # local per-model "id" links
321
+ links do
322
+ property :album_id, :as => :album
323
+ collection :musician_ids, :as => :musicians
324
+ end
325
+ has_one :composer
326
+ has_many :listeners
313
327
 
314
328
 
315
- # global document links.
316
- link "songs.album" do
317
- {
318
- type: "album",
319
- href: "http://example.com/albums/{songs.album}"
320
- }
329
+ # global document links.
330
+ link "songs.album" do
331
+ {
332
+ type: "album",
333
+ href: "http://example.com/albums/{songs.album}"
334
+ }
335
+ end
321
336
  end
322
- end
323
337
 
324
- subject { [song, song].extend(Singular.for_collection) }
338
+ subject { [song, song].extend(Singular.for_collection) }
325
339
 
326
- # to_json
327
- it do
328
- subject.extend(Representer.for_collection).to_hash.must_equal(
329
- {
330
- "songs"=>[{"id"=>"1", "title"=>"Computadores Fazem Arte", "links"=>{"album"=>"9", "musicians"=>["1", "2"], "composer"=>"10", "listeners"=>["8"]}}, {"id"=>"1", "title"=>"Computadores Fazem Arte", "links"=>{"album"=>"9", "musicians"=>["1", "2"], "composer"=>"10", "listeners"=>["8"]}}],
331
- "links"=>{"songs.album"=>{"href"=>"http://example.com/albums/{songs.album}", "type"=>"album"}
340
+ # to_json
341
+ it do
342
+ subject.extend(Representer.for_collection).to_hash.must_equal(
343
+ {
344
+ "songs"=>[{"id"=>"1", "title"=>"Computadores Fazem Arte", "links"=>{"album"=>"9", "musicians"=>["1", "2"], "composer"=>"10", "listeners"=>["8"]}}, {"id"=>"1", "title"=>"Computadores Fazem Arte", "links"=>{"album"=>"9", "musicians"=>["1", "2"], "composer"=>"10", "listeners"=>["8"]}}],
345
+ "links"=>{"songs.album"=>{"href"=>"http://example.com/albums/{songs.album}", "type"=>"album"}
346
+ }
332
347
  }
333
- }
334
- )
348
+ )
349
+ end
335
350
  end
336
- end
337
351
 
338
352
 
339
- class ExplicitMeta < self
340
- module Representer
341
- include Roar::JSON::JSONAPI
353
+ class ExplicitMeta < self
354
+ module Representer
355
+ include Roar::JSON::JSONAPI
342
356
 
343
- type :songs
344
- property :id
357
+ type :songs
358
+ property :id
345
359
 
346
- meta do
347
- property :page
360
+ meta do
361
+ property :page
362
+ end
348
363
  end
349
- end
350
364
 
351
- module Page
352
- def page
353
- 2
365
+ module Page
366
+ def page
367
+ 2
368
+ end
354
369
  end
355
- end
356
370
 
357
- let (:song) { Struct.new(:id).new(1) }
371
+ let (:song) { Struct.new(:id).new(1) }
358
372
 
359
- subject { [song, song].extend(Representer.for_collection).extend(Page) }
373
+ subject { [song, song].extend(Representer.for_collection).extend(Page) }
360
374
 
361
- # to_json
362
- it do
363
- subject.to_hash.must_equal(
364
- {
365
- "songs"=>[{"id"=>1}, {"id"=>1}],
366
- "meta" =>{"page"=>2}
367
- }
368
- )
375
+ # to_json
376
+ it do
377
+ subject.to_hash.must_equal(
378
+ {
379
+ "songs"=>[{"id"=>1}, {"id"=>1}],
380
+ "meta" =>{"page"=>2}
381
+ }
382
+ )
383
+ end
369
384
  end
370
- end
371
385
 
372
386
 
373
- class ImplicitMeta < self
374
- module Representer
375
- include Roar::JSON::JSONAPI
387
+ class ImplicitMeta < self
388
+ module Representer
389
+ include Roar::JSON::JSONAPI
376
390
 
377
- type :songs
378
- property :id
379
- end
391
+ type :songs
392
+ property :id
393
+ end
380
394
 
381
- let (:song) { Struct.new(:id).new(1) }
395
+ let (:song) { Struct.new(:id).new(1) }
382
396
 
383
- subject { [song, song].extend(Representer.for_collection) }
397
+ subject { [song, song].extend(Representer.for_collection) }
384
398
 
385
- # to_json
386
- it do
387
- subject.to_hash("meta" => {"page" => 2}).must_equal(
388
- {
389
- "songs"=>[{"id"=>1}, {"id"=>1}],
390
- "meta" =>{"page"=>2}
391
- }
392
- )
399
+ # to_json
400
+ it do
401
+ subject.to_hash("meta" => {"page" => 2}).must_equal(
402
+ {
403
+ "songs"=>[{"id"=>1}, {"id"=>1}],
404
+ "meta" =>{"page"=>2}
405
+ }
406
+ )
407
+ end
393
408
  end
394
409
  end
395
- end
410
+ end