roar 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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