grape-entity 0.3.0 → 0.4.0
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 +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +69 -0
- data/.travis.yml +5 -6
- data/CHANGELOG.md +35 -0
- data/Gemfile +7 -0
- data/Guardfile +0 -1
- data/README.md +320 -0
- data/Rakefile +3 -33
- data/lib/grape-entity.rb +1 -1
- data/lib/grape_entity.rb +2 -5
- data/lib/grape_entity/entity.rb +190 -71
- data/lib/grape_entity/version.rb +1 -1
- data/spec/grape_entity/entity_spec.rb +539 -158
- metadata +6 -5
- data/CHANGELOG.markdown +0 -21
- data/README.markdown +0 -197
data/lib/grape_entity/version.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Grape::Entity do
|
4
|
+
|
4
5
|
let(:fresh_class) { Class.new(Grape::Entity) }
|
5
6
|
|
6
7
|
context 'class methods' do
|
@@ -14,33 +15,115 @@ describe Grape::Entity do
|
|
14
15
|
end
|
15
16
|
|
16
17
|
it 'sets the same options for all exposures passed' do
|
17
|
-
subject.expose :name, :email, :location, :
|
18
|
-
subject.exposures.values.each{|v| v.should == {:
|
18
|
+
subject.expose :name, :email, :location, documentation: true
|
19
|
+
subject.exposures.values.each { |v| v.should == { documentation: true } }
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
23
|
context 'option validation' do
|
23
24
|
it 'makes sure that :as only works on single attribute calls' do
|
24
|
-
expect{ subject.expose :name, :email, :
|
25
|
-
expect{ subject.expose :name, :
|
25
|
+
expect { subject.expose :name, :email, as: :foo }.to raise_error ArgumentError
|
26
|
+
expect { subject.expose :name, as: :foo }.not_to raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'makes sure that :format_with as a proc cannot be used with a block' do
|
30
|
+
expect { subject.expose :name, format_with: proc {} {} }.to raise_error ArgumentError
|
26
31
|
end
|
27
32
|
|
28
|
-
it 'makes sure
|
29
|
-
expect { subject.expose :name, :
|
33
|
+
it 'makes sure unknown options are not silently ignored' do
|
34
|
+
expect { subject.expose :name, unknown: nil }.to raise_error ArgumentError
|
30
35
|
end
|
31
36
|
end
|
32
37
|
|
33
38
|
context 'with a block' do
|
34
39
|
it 'errors out if called with multiple attributes' do
|
35
|
-
expect{ subject.expose(:name, :email)
|
36
|
-
true
|
37
|
-
end }.to raise_error(ArgumentError)
|
40
|
+
expect { subject.expose(:name, :email) { true } }.to raise_error ArgumentError
|
38
41
|
end
|
39
42
|
|
40
|
-
it '
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
it 'references an instance of the entity with :using option' do
|
44
|
+
module EntitySpec
|
45
|
+
class SomeObject1
|
46
|
+
attr_accessor :prop1
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
@prop1 = "value1"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class BogusEntity < Grape::Entity
|
54
|
+
expose :prop1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
subject.expose(:bogus, using: EntitySpec::BogusEntity) do |entity|
|
59
|
+
entity.prop1 = "MODIFIED 2"
|
60
|
+
entity
|
61
|
+
end
|
62
|
+
|
63
|
+
object = EntitySpec::SomeObject1.new
|
64
|
+
value = subject.represent(object).send(:value_for, :bogus)
|
65
|
+
value.should be_instance_of EntitySpec::BogusEntity
|
66
|
+
|
67
|
+
prop1 = value.send(:value_for, :prop1)
|
68
|
+
prop1.should == "MODIFIED 2"
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'with parameters passed to the block' do
|
72
|
+
it 'sets the :proc option in the exposure options' do
|
73
|
+
block = lambda { |_| true }
|
74
|
+
subject.expose :name, using: 'Awesome', &block
|
75
|
+
subject.exposures[:name].should == { proc: block, using: 'Awesome' }
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'references an instance of the entity without any options' do
|
79
|
+
subject.expose(:size) { |_| self }
|
80
|
+
subject.represent(Hash.new).send(:value_for, :size).should be_an_instance_of fresh_class
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'with no parameters passed to the block' do
|
85
|
+
it 'adds a nested exposure' do
|
86
|
+
subject.expose :awesome do
|
87
|
+
subject.expose :nested do
|
88
|
+
subject.expose :moar_nested, as: 'weee'
|
89
|
+
end
|
90
|
+
subject.expose :another_nested, using: 'Awesome'
|
91
|
+
end
|
92
|
+
|
93
|
+
subject.exposures.should == {
|
94
|
+
awesome: {},
|
95
|
+
awesome__nested: {},
|
96
|
+
awesome__nested__moar_nested: { as: 'weee' },
|
97
|
+
awesome__another_nested: { using: 'Awesome' }
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'represents the exposure as a hash of its nested exposures' do
|
102
|
+
subject.expose :awesome do
|
103
|
+
subject.expose(:nested) { |_| "value" }
|
104
|
+
subject.expose(:another_nested) { |_| "value" }
|
105
|
+
end
|
106
|
+
|
107
|
+
subject.represent({}).send(:value_for, :awesome).should == {
|
108
|
+
nested: "value",
|
109
|
+
another_nested: "value"
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'is safe if its nested exposures are safe' do
|
114
|
+
subject.with_options safe: true do
|
115
|
+
subject.expose :awesome do
|
116
|
+
subject.expose(:nested) { |_| "value" }
|
117
|
+
end
|
118
|
+
subject.expose :not_awesome do
|
119
|
+
subject.expose :nested
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
valid_keys = subject.represent({}).valid_exposures.keys
|
124
|
+
valid_keys.include?(:awesome).should == true && \
|
125
|
+
valid_keys.include?(:not_awesome).should == false
|
126
|
+
end
|
44
127
|
end
|
45
128
|
end
|
46
129
|
|
@@ -73,7 +156,7 @@ describe Grape::Entity do
|
|
73
156
|
end
|
74
157
|
|
75
158
|
context 'register formatters' do
|
76
|
-
let(:date_formatter) { lambda {|date| date.strftime('%m/%d/%Y') }}
|
159
|
+
let(:date_formatter) { lambda { |date| date.strftime('%m/%d/%Y') } }
|
77
160
|
|
78
161
|
it 'registers a formatter' do
|
79
162
|
subject.format_with :timestamp, &date_formatter
|
@@ -89,7 +172,7 @@ describe Grape::Entity do
|
|
89
172
|
end
|
90
173
|
|
91
174
|
it 'does not allow registering a formatter without a block' do
|
92
|
-
expect{ subject.format_with :foo }.to raise_error
|
175
|
+
expect { subject.format_with :foo }.to raise_error ArgumentError
|
93
176
|
end
|
94
177
|
|
95
178
|
it 'formats an exposure with a registered formatter' do
|
@@ -97,45 +180,164 @@ describe Grape::Entity do
|
|
97
180
|
date.strftime('%m/%d/%Y')
|
98
181
|
end
|
99
182
|
|
100
|
-
subject.expose :birthday, :
|
183
|
+
subject.expose :birthday, format_with: :timestamp
|
184
|
+
|
185
|
+
model = { birthday: Time.gm(2012, 2, 27) }
|
186
|
+
subject.new(double(model)).as_json[:birthday].should == '02/27/2012'
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'formats an exposure with a :format_with lambda that returns a value from the entity instance' do
|
190
|
+
object = Hash.new
|
101
191
|
|
102
|
-
|
103
|
-
subject.
|
192
|
+
subject.expose(:size, format_with: lambda { |value| self.object.class.to_s })
|
193
|
+
subject.represent(object).send(:value_for, :size).should == object.class.to_s
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'formats an exposure with a :format_with symbol that returns a value from the entity instance' do
|
197
|
+
subject.format_with :size_formatter do |date|
|
198
|
+
self.object.class.to_s
|
199
|
+
end
|
200
|
+
|
201
|
+
object = Hash.new
|
202
|
+
|
203
|
+
subject.expose(:size, format_with: :size_formatter)
|
204
|
+
subject.represent(object).send(:value_for, :size).should == object.class.to_s
|
104
205
|
end
|
105
206
|
end
|
106
207
|
end
|
107
208
|
|
108
209
|
describe '.with_options' do
|
109
|
-
it '
|
210
|
+
it 'raises an error for unknown options' do
|
211
|
+
block = proc do
|
212
|
+
with_options(unknown: true) do
|
213
|
+
expose :awesome_thing
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
expect { subject.class_eval(&block) }.to raise_error ArgumentError
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'applies the options to all exposures inside' do
|
110
221
|
subject.class_eval do
|
111
|
-
with_options(:
|
112
|
-
expose :awesome_thing, :
|
222
|
+
with_options(if: { awesome: true }) do
|
223
|
+
expose :awesome_thing, using: 'Awesome'
|
113
224
|
end
|
114
225
|
end
|
115
226
|
|
116
|
-
subject.exposures[:awesome_thing].should == {:
|
227
|
+
subject.exposures[:awesome_thing].should == { if: { awesome: true }, using: 'Awesome' }
|
117
228
|
end
|
118
229
|
|
119
|
-
it '
|
230
|
+
it 'allows for nested .with_options' do
|
120
231
|
subject.class_eval do
|
121
|
-
with_options(:
|
122
|
-
with_options(:
|
232
|
+
with_options(if: { awesome: true }) do
|
233
|
+
with_options(using: 'Something') do
|
123
234
|
expose :awesome_thing
|
124
235
|
end
|
125
236
|
end
|
126
237
|
end
|
127
238
|
|
128
|
-
subject.exposures[:awesome_thing].should == {:
|
239
|
+
subject.exposures[:awesome_thing].should == { if: { awesome: true }, using: 'Something' }
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'overrides nested :as option' do
|
243
|
+
subject.class_eval do
|
244
|
+
with_options(as: :sweet) do
|
245
|
+
expose :awesome_thing, as: :extra_smooth
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
subject.exposures[:awesome_thing].should == { as: :extra_smooth }
|
250
|
+
end
|
251
|
+
|
252
|
+
it "merges nested :if option" do
|
253
|
+
match_proc = lambda { |obj, opts| true }
|
254
|
+
|
255
|
+
subject.class_eval do
|
256
|
+
# Symbol
|
257
|
+
with_options(if: :awesome) do
|
258
|
+
# Hash
|
259
|
+
with_options(if: { awesome: true }) do
|
260
|
+
# Proc
|
261
|
+
with_options(if: match_proc) do
|
262
|
+
# Hash (override existing key and merge new key)
|
263
|
+
with_options(if: { awesome: false, less_awesome: true }) do
|
264
|
+
expose :awesome_thing
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
subject.exposures[:awesome_thing].should == {
|
272
|
+
if: { awesome: false, less_awesome: true },
|
273
|
+
if_extras: [:awesome, match_proc]
|
274
|
+
}
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'merges nested :unless option' do
|
278
|
+
match_proc = lambda { |obj, opts| true }
|
279
|
+
|
280
|
+
subject.class_eval do
|
281
|
+
# Symbol
|
282
|
+
with_options(unless: :awesome) do
|
283
|
+
# Hash
|
284
|
+
with_options(unless: { awesome: true }) do
|
285
|
+
# Proc
|
286
|
+
with_options(unless: match_proc) do
|
287
|
+
# Hash (override existing key and merge new key)
|
288
|
+
with_options(unless: { awesome: false, less_awesome: true }) do
|
289
|
+
expose :awesome_thing
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
subject.exposures[:awesome_thing].should == {
|
297
|
+
unless: { awesome: false, less_awesome: true },
|
298
|
+
unless_extras: [:awesome, match_proc]
|
299
|
+
}
|
129
300
|
end
|
130
301
|
|
131
|
-
it '
|
302
|
+
it 'overrides nested :using option' do
|
132
303
|
subject.class_eval do
|
133
|
-
with_options(:
|
134
|
-
expose :
|
304
|
+
with_options(using: 'Something') do
|
305
|
+
expose :awesome_thing, using: 'SomethingElse'
|
135
306
|
end
|
136
307
|
end
|
137
308
|
|
138
|
-
subject.exposures[:
|
309
|
+
subject.exposures[:awesome_thing].should == { using: 'SomethingElse' }
|
310
|
+
end
|
311
|
+
|
312
|
+
it 'aliases :with option to :using option' do
|
313
|
+
subject.class_eval do
|
314
|
+
with_options(using: 'Something') do
|
315
|
+
expose :awesome_thing, with: 'SomethingElse'
|
316
|
+
end
|
317
|
+
end
|
318
|
+
subject.exposures[:awesome_thing].should == { using: 'SomethingElse' }
|
319
|
+
end
|
320
|
+
|
321
|
+
it 'overrides nested :proc option' do
|
322
|
+
match_proc = lambda { |obj, opts| 'more awesomer' }
|
323
|
+
|
324
|
+
subject.class_eval do
|
325
|
+
with_options(proc: lambda { |obj, opts| 'awesome' }) do
|
326
|
+
expose :awesome_thing, proc: match_proc
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
subject.exposures[:awesome_thing].should == { proc: match_proc }
|
331
|
+
end
|
332
|
+
|
333
|
+
it 'overrides nested :documentation option' do
|
334
|
+
subject.class_eval do
|
335
|
+
with_options(documentation: { desc: 'Description.' }) do
|
336
|
+
expose :awesome_thing, documentation: { desc: 'Other description.' }
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
subject.exposures[:awesome_thing].should == { documentation: { desc: 'Other description.' } }
|
139
341
|
end
|
140
342
|
end
|
141
343
|
|
@@ -149,15 +351,27 @@ describe Grape::Entity do
|
|
149
351
|
end
|
150
352
|
|
151
353
|
it 'returns multiple entities if called with a collection' do
|
152
|
-
representation = subject.represent(4.times.map{Object.new})
|
354
|
+
representation = subject.represent(4.times.map { Object.new })
|
153
355
|
representation.should be_kind_of Array
|
154
356
|
representation.size.should == 4
|
155
|
-
representation.reject{|r| r.kind_of?(subject)}.should be_empty
|
357
|
+
representation.reject { |r| r.kind_of?(subject) }.should be_empty
|
156
358
|
end
|
157
359
|
|
158
|
-
it 'adds the :
|
159
|
-
representation = subject.represent(4.times.map{Object.new})
|
160
|
-
representation.each{|r| r.options[:collection].should be_true}
|
360
|
+
it 'adds the collection: true option if called with a collection' do
|
361
|
+
representation = subject.represent(4.times.map { Object.new })
|
362
|
+
representation.each { |r| r.options[:collection].should be_true }
|
363
|
+
end
|
364
|
+
|
365
|
+
it 'returns a serialized hash of a single object if serializable: true' do
|
366
|
+
subject.expose(:awesome) { |_| true }
|
367
|
+
representation = subject.represent(Object.new, serializable: true)
|
368
|
+
representation.should == { awesome: true }
|
369
|
+
end
|
370
|
+
|
371
|
+
it 'returns a serialized array of hashes of multiple objects if serializable: true' do
|
372
|
+
subject.expose(:awesome) { |_| true }
|
373
|
+
representation = subject.represent(2.times.map { Object.new }, serializable: true)
|
374
|
+
representation.should == [{ awesome: true }, { awesome: true }]
|
161
375
|
end
|
162
376
|
end
|
163
377
|
|
@@ -178,29 +392,29 @@ describe Grape::Entity do
|
|
178
392
|
|
179
393
|
context 'with an array of objects' do
|
180
394
|
it 'allows a root element name to be specified' do
|
181
|
-
representation = subject.represent(4.times.map{Object.new})
|
395
|
+
representation = subject.represent(4.times.map { Object.new })
|
182
396
|
representation.should be_kind_of Hash
|
183
397
|
representation.should have_key 'things'
|
184
398
|
representation['things'].should be_kind_of Array
|
185
399
|
representation['things'].size.should == 4
|
186
|
-
representation['things'].reject{|r| r.kind_of?(subject)}.should be_empty
|
400
|
+
representation['things'].reject { |r| r.kind_of?(subject) }.should be_empty
|
187
401
|
end
|
188
402
|
end
|
189
403
|
|
190
404
|
context 'it can be overridden' do
|
191
405
|
it 'can be disabled' do
|
192
|
-
representation = subject.represent(4.times.map{Object.new}, :
|
406
|
+
representation = subject.represent(4.times.map { Object.new }, root: false)
|
193
407
|
representation.should be_kind_of Array
|
194
408
|
representation.size.should == 4
|
195
|
-
representation.reject{|r| r.kind_of?(subject)}.should be_empty
|
409
|
+
representation.reject { |r| r.kind_of?(subject) }.should be_empty
|
196
410
|
end
|
197
411
|
it 'can use a different name' do
|
198
|
-
representation = subject.represent(4.times.map{Object.new}, :
|
412
|
+
representation = subject.represent(4.times.map { Object.new }, root: 'others')
|
199
413
|
representation.should be_kind_of Hash
|
200
414
|
representation.should have_key 'others'
|
201
415
|
representation['others'].should be_kind_of Array
|
202
416
|
representation['others'].size.should == 4
|
203
|
-
representation['others'].reject{|r| r.kind_of?(subject)}.should be_empty
|
417
|
+
representation['others'].reject { |r| r.kind_of?(subject) }.should be_empty
|
204
418
|
end
|
205
419
|
end
|
206
420
|
end
|
@@ -221,10 +435,10 @@ describe Grape::Entity do
|
|
221
435
|
|
222
436
|
context 'with an array of objects' do
|
223
437
|
it 'allows a root element name to be specified' do
|
224
|
-
representation = subject.represent(4.times.map{Object.new})
|
438
|
+
representation = subject.represent(4.times.map { Object.new })
|
225
439
|
representation.should be_kind_of Array
|
226
440
|
representation.size.should == 4
|
227
|
-
representation.reject{|r| r.kind_of?(subject)}.should be_empty
|
441
|
+
representation.reject { |r| r.kind_of?(subject) }.should be_empty
|
228
442
|
end
|
229
443
|
end
|
230
444
|
end
|
@@ -242,12 +456,12 @@ describe Grape::Entity do
|
|
242
456
|
|
243
457
|
context 'with an array of objects' do
|
244
458
|
it 'allows a root element name to be specified' do
|
245
|
-
representation = subject.represent(4.times.map{Object.new})
|
459
|
+
representation = subject.represent(4.times.map { Object.new })
|
246
460
|
representation.should be_kind_of Hash
|
247
461
|
representation.should have_key('things')
|
248
462
|
representation['things'].should be_kind_of Array
|
249
463
|
representation['things'].size.should == 4
|
250
|
-
representation['things'].reject{|r| r.kind_of?(subject)}.should be_empty
|
464
|
+
representation['things'].reject { |r| r.kind_of?(subject) }.should be_empty
|
251
465
|
end
|
252
466
|
end
|
253
467
|
end
|
@@ -255,9 +469,9 @@ describe Grape::Entity do
|
|
255
469
|
|
256
470
|
describe '#initialize' do
|
257
471
|
it 'takes an object and an optional options hash' do
|
258
|
-
expect{ subject.new(Object.new) }.not_to raise_error
|
259
|
-
expect{ subject.new }.to raise_error
|
260
|
-
expect{ subject.new(Object.new, {}) }.not_to raise_error
|
472
|
+
expect { subject.new(Object.new) }.not_to raise_error
|
473
|
+
expect { subject.new }.to raise_error ArgumentError
|
474
|
+
expect { subject.new(Object.new, {}) }.not_to raise_error
|
261
475
|
end
|
262
476
|
|
263
477
|
it 'has attribute readers for the object and options' do
|
@@ -266,63 +480,95 @@ describe Grape::Entity do
|
|
266
480
|
entity.options.should == {}
|
267
481
|
end
|
268
482
|
end
|
483
|
+
|
269
484
|
end
|
270
485
|
|
271
486
|
context 'instance methods' do
|
272
|
-
|
273
|
-
let(:model){ mock(attributes) }
|
274
|
-
|
275
|
-
let(:attributes) { {
|
276
|
-
:name => 'Bob Bobson',
|
277
|
-
:email => 'bob@example.com',
|
278
|
-
:birthday => Time.gm(2012, 2, 27),
|
279
|
-
:fantasies => ['Unicorns', 'Double Rainbows', 'Nessy'],
|
280
|
-
:friends => [
|
281
|
-
mock(:name => "Friend 1", :email => 'friend1@example.com', :fantasies => [], :birthday => Time.gm(2012, 2, 27), :friends => []),
|
282
|
-
mock(:name => "Friend 2", :email => 'friend2@example.com', :fantasies => [], :birthday => Time.gm(2012, 2, 27), :friends => [])
|
283
|
-
]
|
284
|
-
} }
|
285
|
-
|
286
|
-
subject{ fresh_class.new(model) }
|
287
487
|
|
288
|
-
|
488
|
+
let(:model) { double(attributes) }
|
289
489
|
|
490
|
+
let(:attributes) {
|
491
|
+
{
|
492
|
+
name: 'Bob Bobson',
|
493
|
+
email: 'bob@example.com',
|
494
|
+
birthday: Time.gm(2012, 2, 27),
|
495
|
+
fantasies: ['Unicorns', 'Double Rainbows', 'Nessy'],
|
496
|
+
friends: [
|
497
|
+
double(name: "Friend 1", email: 'friend1@example.com', fantasies: [], birthday: Time.gm(2012, 2, 27), friends: []),
|
498
|
+
double(name: "Friend 2", email: 'friend2@example.com', fantasies: [], birthday: Time.gm(2012, 2, 27), friends: [])
|
499
|
+
]
|
500
|
+
}
|
501
|
+
}
|
502
|
+
|
503
|
+
subject { fresh_class.new(model) }
|
504
|
+
|
505
|
+
describe '#serializable_hash' do
|
290
506
|
it 'does not throw an exception if a nil options object is passed' do
|
291
|
-
expect{ fresh_class.new(model).serializable_hash(nil) }.not_to raise_error
|
507
|
+
expect { fresh_class.new(model).serializable_hash(nil) }.not_to raise_error
|
292
508
|
end
|
293
509
|
|
294
510
|
it 'does not blow up when the model is nil' do
|
295
511
|
fresh_class.expose :name
|
296
|
-
expect{ fresh_class.new(nil).serializable_hash }.not_to raise_error
|
512
|
+
expect { fresh_class.new(nil).serializable_hash }.not_to raise_error
|
297
513
|
end
|
298
514
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
515
|
+
context "with safe option" do
|
516
|
+
it 'does not throw an exception when an attribute is not found on the object' do
|
517
|
+
fresh_class.expose :name, :nonexistent_attribute, safe: true
|
518
|
+
expect { fresh_class.new(model).serializable_hash }.not_to raise_error
|
519
|
+
end
|
303
520
|
|
304
|
-
|
305
|
-
|
521
|
+
it "does not expose attributes that don't exist on the object" do
|
522
|
+
fresh_class.expose :email, :nonexistent_attribute, :name, safe: true
|
306
523
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
524
|
+
res = fresh_class.new(model).serializable_hash
|
525
|
+
res.should have_key :email
|
526
|
+
res.should_not have_key :nonexistent_attribute
|
527
|
+
res.should have_key :name
|
528
|
+
end
|
529
|
+
|
530
|
+
it "does not expose attributes that don't exist on the object, even with criteria" do
|
531
|
+
fresh_class.expose :email
|
532
|
+
fresh_class.expose :nonexistent_attribute, safe: true, if: lambda { false }
|
533
|
+
fresh_class.expose :nonexistent_attribute2, safe: true, if: lambda { true }
|
534
|
+
|
535
|
+
res = fresh_class.new(model).serializable_hash
|
536
|
+
res.should have_key :email
|
537
|
+
res.should_not have_key :nonexistent_attribute
|
538
|
+
res.should_not have_key :nonexistent_attribute2
|
539
|
+
end
|
311
540
|
end
|
312
541
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
542
|
+
context "without safe option" do
|
543
|
+
it 'throws an exception when an attribute is not found on the object' do
|
544
|
+
fresh_class.expose :name, :nonexistent_attribute
|
545
|
+
expect { fresh_class.new(model).serializable_hash }.to raise_error
|
546
|
+
end
|
317
547
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
548
|
+
it "exposes attributes that don't exist on the object only when they are generated by a block" do
|
549
|
+
fresh_class.expose :nonexistent_attribute do |model, _|
|
550
|
+
"well, I do exist after all"
|
551
|
+
end
|
552
|
+
res = fresh_class.new(model).serializable_hash
|
553
|
+
res.should have_key :nonexistent_attribute
|
554
|
+
end
|
555
|
+
|
556
|
+
it "does not expose attributes that are generated by a block but have not passed criteria" do
|
557
|
+
fresh_class.expose :nonexistent_attribute, proc: lambda { |model, _|
|
558
|
+
"I exist, but it is not yet my time to shine"
|
559
|
+
}, if: lambda { |model, _| false }
|
560
|
+
res = fresh_class.new(model).serializable_hash
|
561
|
+
res.should_not have_key :nonexistent_attribute
|
562
|
+
end
|
322
563
|
end
|
323
564
|
|
324
|
-
it "exposes attributes that don't exist on the object only when they are generated by a block" do
|
325
|
-
|
565
|
+
it "exposes attributes that don't exist on the object only when they are generated by a block with options" do
|
566
|
+
module EntitySpec
|
567
|
+
class TestEntity < Grape::Entity
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
fresh_class.expose :nonexistent_attribute, using: EntitySpec::TestEntity do |model, _|
|
326
572
|
"well, I do exist after all"
|
327
573
|
end
|
328
574
|
res = fresh_class.new(model).serializable_hash
|
@@ -330,71 +576,88 @@ describe Grape::Entity do
|
|
330
576
|
end
|
331
577
|
|
332
578
|
it "does not expose attributes that are generated by a block but have not passed criteria" do
|
333
|
-
fresh_class.expose :nonexistent_attribute, :
|
579
|
+
fresh_class.expose :nonexistent_attribute, proc: lambda { |model, _|
|
334
580
|
"I exist, but it is not yet my time to shine"
|
335
|
-
},
|
581
|
+
}, if: lambda { |model, _| false }
|
336
582
|
res = fresh_class.new(model).serializable_hash
|
337
583
|
res.should_not have_key :nonexistent_attribute
|
338
584
|
end
|
339
585
|
|
340
586
|
context '#serializable_hash' do
|
341
|
-
|
342
587
|
module EntitySpec
|
343
588
|
class EmbeddedExample
|
344
589
|
def serializable_hash(opts = {})
|
345
|
-
{ :
|
590
|
+
{ abc: 'def' }
|
346
591
|
end
|
347
592
|
end
|
593
|
+
|
594
|
+
class EmbeddedExampleWithHash
|
595
|
+
def name
|
596
|
+
"abc"
|
597
|
+
end
|
598
|
+
|
599
|
+
def embedded
|
600
|
+
{ a: nil, b: EmbeddedExample.new }
|
601
|
+
end
|
602
|
+
end
|
603
|
+
|
348
604
|
class EmbeddedExampleWithMany
|
349
605
|
def name
|
350
606
|
"abc"
|
351
607
|
end
|
608
|
+
|
352
609
|
def embedded
|
353
|
-
[
|
610
|
+
[EmbeddedExample.new, EmbeddedExample.new]
|
354
611
|
end
|
355
612
|
end
|
613
|
+
|
356
614
|
class EmbeddedExampleWithOne
|
357
615
|
def name
|
358
616
|
"abc"
|
359
617
|
end
|
618
|
+
|
360
619
|
def embedded
|
361
620
|
EmbeddedExample.new
|
362
621
|
end
|
363
622
|
end
|
364
623
|
end
|
365
|
-
|
624
|
+
|
366
625
|
it 'serializes embedded objects which respond to #serializable_hash' do
|
367
626
|
fresh_class.expose :name, :embedded
|
368
627
|
presenter = fresh_class.new(EntitySpec::EmbeddedExampleWithOne.new)
|
369
|
-
presenter.serializable_hash.should == {:
|
628
|
+
presenter.serializable_hash.should == { name: "abc", embedded: { abc: "def" } }
|
370
629
|
end
|
371
630
|
|
372
631
|
it 'serializes embedded arrays of objects which respond to #serializable_hash' do
|
373
632
|
fresh_class.expose :name, :embedded
|
374
633
|
presenter = fresh_class.new(EntitySpec::EmbeddedExampleWithMany.new)
|
375
|
-
presenter.serializable_hash.should == {:
|
634
|
+
presenter.serializable_hash.should == { name: "abc", embedded: [{ abc: "def" }, { abc: "def" }] }
|
635
|
+
end
|
636
|
+
|
637
|
+
it 'serializes embedded hashes of objects which respond to #serializable_hash' do
|
638
|
+
fresh_class.expose :name, :embedded
|
639
|
+
presenter = fresh_class.new(EntitySpec::EmbeddedExampleWithHash.new)
|
640
|
+
presenter.serializable_hash.should == { name: "abc", embedded: { a: nil, b: { abc: "def" } } }
|
376
641
|
end
|
377
|
-
|
378
642
|
end
|
379
|
-
|
380
643
|
end
|
381
644
|
|
382
645
|
describe '#value_for' do
|
383
646
|
before do
|
384
647
|
fresh_class.class_eval do
|
385
648
|
expose :name, :email
|
386
|
-
expose :friends, :
|
649
|
+
expose :friends, using: self
|
387
650
|
expose :computed do |_, options|
|
388
651
|
options[:awesome]
|
389
652
|
end
|
390
653
|
|
391
|
-
expose :birthday, :
|
654
|
+
expose :birthday, format_with: :timestamp
|
392
655
|
|
393
656
|
def timestamp(date)
|
394
657
|
date.strftime('%m/%d/%Y')
|
395
658
|
end
|
396
659
|
|
397
|
-
expose :fantasies, :
|
660
|
+
expose :fantasies, format_with: lambda { |f| f.reverse }
|
398
661
|
end
|
399
662
|
end
|
400
663
|
|
@@ -404,54 +667,112 @@ describe Grape::Entity do
|
|
404
667
|
|
405
668
|
it 'instantiates a representation if that is called for' do
|
406
669
|
rep = subject.send(:value_for, :friends)
|
407
|
-
rep.reject{|r| r.is_a?(fresh_class)}.should be_empty
|
670
|
+
rep.reject { |r| r.is_a?(fresh_class) }.should be_empty
|
408
671
|
rep.first.serializable_hash[:name].should == 'Friend 1'
|
409
672
|
rep.last.serializable_hash[:name].should == 'Friend 2'
|
410
673
|
end
|
411
674
|
|
412
675
|
context 'child representations' do
|
413
676
|
it 'disables root key name for child representations' do
|
414
|
-
|
415
677
|
module EntitySpec
|
416
678
|
class FriendEntity < Grape::Entity
|
417
679
|
root 'friends', 'friend'
|
418
680
|
expose :name, :email
|
419
681
|
end
|
420
682
|
end
|
421
|
-
|
683
|
+
|
422
684
|
fresh_class.class_eval do
|
423
|
-
expose :friends, :
|
685
|
+
expose :friends, using: EntitySpec::FriendEntity
|
424
686
|
end
|
425
|
-
|
687
|
+
|
426
688
|
rep = subject.send(:value_for, :friends)
|
427
689
|
rep.should be_kind_of Array
|
428
|
-
rep.reject{|r| r.is_a?(EntitySpec::FriendEntity)}.should be_empty
|
690
|
+
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.should be_empty
|
429
691
|
rep.first.serializable_hash[:name].should == 'Friend 1'
|
430
692
|
rep.last.serializable_hash[:name].should == 'Friend 2'
|
431
693
|
end
|
432
694
|
|
695
|
+
it "passes through the proc which returns an array of objects with custom options(:using)" do
|
696
|
+
module EntitySpec
|
697
|
+
class FriendEntity < Grape::Entity
|
698
|
+
root 'friends', 'friend'
|
699
|
+
expose :name, :email
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
fresh_class.class_eval do
|
704
|
+
expose :custom_friends, using: EntitySpec::FriendEntity do |user, options|
|
705
|
+
user.friends
|
706
|
+
end
|
707
|
+
end
|
708
|
+
|
709
|
+
rep = subject.send(:value_for, :custom_friends)
|
710
|
+
rep.should be_kind_of Array
|
711
|
+
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.should be_empty
|
712
|
+
rep.first.serializable_hash.should == { name: 'Friend 1', email: 'friend1@example.com' }
|
713
|
+
rep.last.serializable_hash.should == { name: 'Friend 2', email: 'friend2@example.com' }
|
714
|
+
end
|
715
|
+
|
716
|
+
it "passes through the proc which returns single object with custom options(:using)" do
|
717
|
+
module EntitySpec
|
718
|
+
class FriendEntity < Grape::Entity
|
719
|
+
root 'friends', 'friend'
|
720
|
+
expose :name, :email
|
721
|
+
end
|
722
|
+
end
|
723
|
+
|
724
|
+
fresh_class.class_eval do
|
725
|
+
expose :first_friend, using: EntitySpec::FriendEntity do |user, options|
|
726
|
+
user.friends.first
|
727
|
+
end
|
728
|
+
end
|
729
|
+
|
730
|
+
rep = subject.send(:value_for, :first_friend)
|
731
|
+
rep.should be_kind_of EntitySpec::FriendEntity
|
732
|
+
rep.serializable_hash.should == { name: 'Friend 1', email: 'friend1@example.com' }
|
733
|
+
end
|
734
|
+
|
735
|
+
it "passes through the proc which returns empty with custom options(:using)" do
|
736
|
+
module EntitySpec
|
737
|
+
class FriendEntity < Grape::Entity
|
738
|
+
root 'friends', 'friend'
|
739
|
+
expose :name, :email
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
fresh_class.class_eval do
|
744
|
+
expose :first_friend, using: EntitySpec::FriendEntity do |user, options|
|
745
|
+
|
746
|
+
end
|
747
|
+
end
|
748
|
+
|
749
|
+
rep = subject.send(:value_for, :first_friend)
|
750
|
+
rep.should be_kind_of EntitySpec::FriendEntity
|
751
|
+
rep.serializable_hash.should be_nil
|
752
|
+
end
|
753
|
+
|
433
754
|
it 'passes through custom options' do
|
434
755
|
module EntitySpec
|
435
756
|
class FriendEntity < Grape::Entity
|
436
757
|
root 'friends', 'friend'
|
437
758
|
expose :name
|
438
|
-
expose :email, :
|
759
|
+
expose :email, if: { user_type: :admin }
|
439
760
|
end
|
440
761
|
end
|
441
|
-
|
762
|
+
|
442
763
|
fresh_class.class_eval do
|
443
|
-
expose :friends, :
|
764
|
+
expose :friends, using: EntitySpec::FriendEntity
|
444
765
|
end
|
445
|
-
|
766
|
+
|
446
767
|
rep = subject.send(:value_for, :friends)
|
447
768
|
rep.should be_kind_of Array
|
448
|
-
rep.reject{|r| r.is_a?(EntitySpec::FriendEntity)}.should be_empty
|
769
|
+
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.should be_empty
|
449
770
|
rep.first.serializable_hash[:email].should be_nil
|
450
771
|
rep.last.serializable_hash[:email].should be_nil
|
451
772
|
|
452
|
-
rep = subject.send(:value_for, :friends,
|
773
|
+
rep = subject.send(:value_for, :friends, user_type: :admin)
|
453
774
|
rep.should be_kind_of Array
|
454
|
-
rep.reject{|r| r.is_a?(EntitySpec::FriendEntity)}.should be_empty
|
775
|
+
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.should be_empty
|
455
776
|
rep.first.serializable_hash[:email].should == 'friend1@example.com'
|
456
777
|
rep.last.serializable_hash[:email].should == 'friend2@example.com'
|
457
778
|
end
|
@@ -461,25 +782,24 @@ describe Grape::Entity do
|
|
461
782
|
class FriendEntity < Grape::Entity
|
462
783
|
root 'friends', 'friend'
|
463
784
|
expose :name
|
464
|
-
expose :email, :
|
785
|
+
expose :email, if: { collection: true }
|
465
786
|
end
|
466
787
|
end
|
467
|
-
|
788
|
+
|
468
789
|
fresh_class.class_eval do
|
469
|
-
expose :friends, :
|
790
|
+
expose :friends, using: EntitySpec::FriendEntity
|
470
791
|
end
|
471
|
-
|
472
|
-
rep = subject.send(:value_for, :friends,
|
792
|
+
|
793
|
+
rep = subject.send(:value_for, :friends, collection: false)
|
473
794
|
rep.should be_kind_of Array
|
474
|
-
rep.reject{|r| r.is_a?(EntitySpec::FriendEntity)}.should be_empty
|
795
|
+
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.should be_empty
|
475
796
|
rep.first.serializable_hash[:email].should == 'friend1@example.com'
|
476
797
|
rep.last.serializable_hash[:email].should == 'friend2@example.com'
|
477
798
|
end
|
478
|
-
|
479
799
|
end
|
480
800
|
|
481
801
|
it 'calls through to the proc if there is one' do
|
482
|
-
subject.send(:value_for, :computed, :
|
802
|
+
subject.send(:value_for, :computed, awesome: 123).should == 123
|
483
803
|
end
|
484
804
|
|
485
805
|
it 'returns a formatted value if format_with is passed' do
|
@@ -489,6 +809,58 @@ describe Grape::Entity do
|
|
489
809
|
it 'returns a formatted value if format_with is passed a lambda' do
|
490
810
|
subject.send(:value_for, :fantasies).should == ['Nessy', 'Double Rainbows', 'Unicorns']
|
491
811
|
end
|
812
|
+
|
813
|
+
it "tries instance methods on the entity first" do
|
814
|
+
module EntitySpec
|
815
|
+
class DelegatingEntity < Grape::Entity
|
816
|
+
root 'friends', 'friend'
|
817
|
+
expose :name
|
818
|
+
expose :email
|
819
|
+
|
820
|
+
private
|
821
|
+
|
822
|
+
def name
|
823
|
+
"cooler name"
|
824
|
+
end
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
828
|
+
friend = double("Friend", name: "joe", email: "joe@example.com")
|
829
|
+
rep = EntitySpec::DelegatingEntity.new(friend)
|
830
|
+
rep.send(:value_for, :name).should == "cooler name"
|
831
|
+
rep.send(:value_for, :email).should == "joe@example.com"
|
832
|
+
end
|
833
|
+
|
834
|
+
context "using" do
|
835
|
+
before do
|
836
|
+
module EntitySpec
|
837
|
+
class UserEntity < Grape::Entity
|
838
|
+
expose :name, :email
|
839
|
+
end
|
840
|
+
end
|
841
|
+
end
|
842
|
+
it "string" do
|
843
|
+
fresh_class.class_eval do
|
844
|
+
expose :friends, using: "EntitySpec::UserEntity"
|
845
|
+
end
|
846
|
+
|
847
|
+
rep = subject.send(:value_for, :friends)
|
848
|
+
rep.should be_kind_of Array
|
849
|
+
rep.size.should == 2
|
850
|
+
rep.all? { |r| r.is_a?(EntitySpec::UserEntity) }.should be_true
|
851
|
+
end
|
852
|
+
|
853
|
+
it 'class' do
|
854
|
+
fresh_class.class_eval do
|
855
|
+
expose :friends, using: EntitySpec::UserEntity
|
856
|
+
end
|
857
|
+
|
858
|
+
rep = subject.send(:value_for, :friends)
|
859
|
+
rep.should be_kind_of Array
|
860
|
+
rep.size.should == 2
|
861
|
+
rep.all? { |r| r.is_a?(EntitySpec::UserEntity) }.should be_true
|
862
|
+
end
|
863
|
+
end
|
492
864
|
end
|
493
865
|
|
494
866
|
describe '#documentation' do
|
@@ -499,89 +871,98 @@ describe Grape::Entity do
|
|
499
871
|
end
|
500
872
|
|
501
873
|
it 'returns each defined documentation hash' do
|
502
|
-
doc = {:
|
503
|
-
fresh_class.expose :name, :
|
504
|
-
fresh_class.expose :email, :
|
874
|
+
doc = { type: "foo", desc: "bar" }
|
875
|
+
fresh_class.expose :name, documentation: doc
|
876
|
+
fresh_class.expose :email, documentation: doc
|
877
|
+
fresh_class.expose :birthday
|
878
|
+
|
879
|
+
subject.documentation.should == { name: doc, email: doc }
|
880
|
+
end
|
881
|
+
|
882
|
+
it 'returns each defined documentation hash with :as param considering' do
|
883
|
+
doc = { type: "foo", desc: "bar" }
|
884
|
+
fresh_class.expose :name, documentation: doc, as: :label
|
885
|
+
fresh_class.expose :email, documentation: doc
|
505
886
|
fresh_class.expose :birthday
|
506
887
|
|
507
|
-
subject.documentation.should == {:
|
888
|
+
subject.documentation.should == { label: doc, email: doc }
|
508
889
|
end
|
509
890
|
end
|
510
891
|
|
511
892
|
describe '#key_for' do
|
512
893
|
it 'returns the attribute if no :as is set' do
|
513
894
|
fresh_class.expose :name
|
514
|
-
subject.send(:key_for, :name).should == :name
|
895
|
+
subject.class.send(:key_for, :name).should == :name
|
515
896
|
end
|
516
897
|
|
517
898
|
it 'returns a symbolized version of the attribute' do
|
518
899
|
fresh_class.expose :name
|
519
|
-
subject.send(:key_for, 'name').should == :name
|
900
|
+
subject.class.send(:key_for, 'name').should == :name
|
520
901
|
end
|
521
902
|
|
522
903
|
it 'returns the :as alias if one exists' do
|
523
|
-
fresh_class.expose :name, :
|
524
|
-
subject.send(:key_for, 'name').should == :nombre
|
904
|
+
fresh_class.expose :name, as: :nombre
|
905
|
+
subject.class.send(:key_for, 'name').should == :nombre
|
525
906
|
end
|
526
907
|
end
|
527
908
|
|
528
909
|
describe '#conditions_met?' do
|
529
910
|
it 'only passes through hash :if exposure if all attributes match' do
|
530
|
-
exposure_options = {:
|
911
|
+
exposure_options = { if: { condition1: true, condition2: true } }
|
531
912
|
|
532
913
|
subject.send(:conditions_met?, exposure_options, {}).should be_false
|
533
|
-
subject.send(:conditions_met?, exposure_options, :
|
534
|
-
subject.send(:conditions_met?, exposure_options, :
|
535
|
-
subject.send(:conditions_met?, exposure_options, :
|
536
|
-
subject.send(:conditions_met?, exposure_options, :
|
914
|
+
subject.send(:conditions_met?, exposure_options, condition1: true).should be_false
|
915
|
+
subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true).should be_true
|
916
|
+
subject.send(:conditions_met?, exposure_options, condition1: false, condition2: true).should be_false
|
917
|
+
subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true, other: true).should be_true
|
537
918
|
end
|
538
919
|
|
539
920
|
it 'looks for presence/truthiness if a symbol is passed' do
|
540
|
-
exposure_options = {:
|
921
|
+
exposure_options = { if: :condition1 }
|
541
922
|
|
542
923
|
subject.send(:conditions_met?, exposure_options, {}).should be_false
|
543
|
-
subject.send(:conditions_met?, exposure_options,
|
544
|
-
subject.send(:conditions_met?, exposure_options,
|
545
|
-
subject.send(:conditions_met?, exposure_options,
|
924
|
+
subject.send(:conditions_met?, exposure_options, condition1: true).should be_true
|
925
|
+
subject.send(:conditions_met?, exposure_options, condition1: false).should be_false
|
926
|
+
subject.send(:conditions_met?, exposure_options, condition1: nil).should be_false
|
546
927
|
end
|
547
928
|
|
548
929
|
it 'looks for absence/falsiness if a symbol is passed' do
|
549
|
-
exposure_options = {:
|
930
|
+
exposure_options = { unless: :condition1 }
|
550
931
|
|
551
932
|
subject.send(:conditions_met?, exposure_options, {}).should be_true
|
552
|
-
subject.send(:conditions_met?, exposure_options,
|
553
|
-
subject.send(:conditions_met?, exposure_options,
|
554
|
-
subject.send(:conditions_met?, exposure_options,
|
933
|
+
subject.send(:conditions_met?, exposure_options, condition1: true).should be_false
|
934
|
+
subject.send(:conditions_met?, exposure_options, condition1: false).should be_true
|
935
|
+
subject.send(:conditions_met?, exposure_options, condition1: nil).should be_true
|
555
936
|
end
|
556
937
|
|
557
938
|
it 'only passes through proc :if exposure if it returns truthy value' do
|
558
|
-
exposure_options = {:
|
939
|
+
exposure_options = { if: lambda { |_, opts| opts[:true] } }
|
559
940
|
|
560
|
-
subject.send(:conditions_met?, exposure_options, :
|
561
|
-
subject.send(:conditions_met?, exposure_options, :
|
941
|
+
subject.send(:conditions_met?, exposure_options, true: false).should be_false
|
942
|
+
subject.send(:conditions_met?, exposure_options, true: true).should be_true
|
562
943
|
end
|
563
944
|
|
564
945
|
it 'only passes through hash :unless exposure if any attributes do not match' do
|
565
|
-
exposure_options = {:
|
946
|
+
exposure_options = { unless: { condition1: true, condition2: true } }
|
566
947
|
|
567
948
|
subject.send(:conditions_met?, exposure_options, {}).should be_true
|
568
|
-
subject.send(:conditions_met?, exposure_options, :
|
569
|
-
subject.send(:conditions_met?, exposure_options, :
|
570
|
-
subject.send(:conditions_met?, exposure_options, :
|
571
|
-
subject.send(:conditions_met?, exposure_options, :
|
572
|
-
subject.send(:conditions_met?, exposure_options, :
|
949
|
+
subject.send(:conditions_met?, exposure_options, condition1: true).should be_false
|
950
|
+
subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true).should be_false
|
951
|
+
subject.send(:conditions_met?, exposure_options, condition1: false, condition2: true).should be_false
|
952
|
+
subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true, other: true).should be_false
|
953
|
+
subject.send(:conditions_met?, exposure_options, condition1: false, condition2: false).should be_true
|
573
954
|
end
|
574
955
|
|
575
956
|
it 'only passes through proc :unless exposure if it returns falsy value' do
|
576
|
-
exposure_options = {:
|
957
|
+
exposure_options = { unless: lambda { |_, options| options[:true] == true } }
|
577
958
|
|
578
|
-
subject.send(:conditions_met?, exposure_options, :
|
579
|
-
subject.send(:conditions_met?, exposure_options, :
|
959
|
+
subject.send(:conditions_met?, exposure_options, true: false).should be_true
|
960
|
+
subject.send(:conditions_met?, exposure_options, true: true).should be_false
|
580
961
|
end
|
581
962
|
end
|
582
963
|
|
583
964
|
describe '::DSL' do
|
584
|
-
subject{ Class.new }
|
965
|
+
subject { Class.new }
|
585
966
|
|
586
967
|
it 'creates an Entity class when called' do
|
587
968
|
subject.should_not be_const_defined :Entity
|
@@ -590,7 +971,7 @@ describe Grape::Entity do
|
|
590
971
|
end
|
591
972
|
|
592
973
|
context 'pre-mixed' do
|
593
|
-
before{ subject.send(:include, Grape::Entity::DSL) }
|
974
|
+
before { subject.send(:include, Grape::Entity::DSL) }
|
594
975
|
|
595
976
|
it 'is able to define entity traits through DSL' do
|
596
977
|
subject.entity do
|
@@ -613,7 +994,7 @@ describe Grape::Entity do
|
|
613
994
|
end
|
614
995
|
|
615
996
|
context 'instance' do
|
616
|
-
let(:instance){ subject.new }
|
997
|
+
let(:instance) { subject.new }
|
617
998
|
|
618
999
|
describe '#entity' do
|
619
1000
|
it 'is an instance of the entity class' do
|
@@ -624,8 +1005,8 @@ describe Grape::Entity do
|
|
624
1005
|
instance.entity.object.should == instance
|
625
1006
|
end
|
626
1007
|
|
627
|
-
it '
|
628
|
-
instance.entity(:
|
1008
|
+
it 'instantiates with options if provided' do
|
1009
|
+
instance.entity(awesome: true).options.should == { awesome: true }
|
629
1010
|
end
|
630
1011
|
end
|
631
1012
|
end
|