grape-entity 0.4.5 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +11 -33
- data/CHANGELOG.md +14 -0
- data/Gemfile +1 -1
- data/README.md +72 -10
- data/lib/grape_entity.rb +1 -0
- data/lib/grape_entity/delegator.rb +23 -0
- data/lib/grape_entity/delegator/base.rb +17 -0
- data/lib/grape_entity/delegator/fetchable_object.rb +11 -0
- data/lib/grape_entity/delegator/hash_object.rb +11 -0
- data/lib/grape_entity/delegator/openstruct_object.rb +11 -0
- data/lib/grape_entity/delegator/plain_object.rb +15 -0
- data/lib/grape_entity/entity.rb +161 -134
- data/lib/grape_entity/version.rb +1 -1
- data/spec/grape_entity/entity_spec.rb +304 -79
- metadata +32 -28
data/lib/grape_entity/version.rb
CHANGED
@@ -70,14 +70,14 @@ describe Grape::Entity do
|
|
70
70
|
|
71
71
|
context 'with parameters passed to the block' do
|
72
72
|
it 'sets the :proc option in the exposure options' do
|
73
|
-
block =
|
73
|
+
block = ->(_) { true }
|
74
74
|
subject.expose :name, using: 'Awesome', &block
|
75
75
|
expect(subject.exposures[:name]).to eq(proc: block, using: 'Awesome')
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'references an instance of the entity without any options' do
|
79
79
|
subject.expose(:size) { |_| self }
|
80
|
-
expect(subject.represent(
|
80
|
+
expect(subject.represent({}).send(:value_for, :size)).to be_an_instance_of fresh_class
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -91,10 +91,10 @@ describe Grape::Entity do
|
|
91
91
|
end
|
92
92
|
|
93
93
|
expect(subject.exposures).to eq(
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
94
|
+
awesome: {},
|
95
|
+
awesome__nested: { nested: true },
|
96
|
+
awesome__nested__moar_nested: { as: 'weee', nested: true },
|
97
|
+
awesome__another_nested: { using: 'Awesome', nested: true }
|
98
98
|
)
|
99
99
|
end
|
100
100
|
|
@@ -105,15 +105,15 @@ describe Grape::Entity do
|
|
105
105
|
end
|
106
106
|
|
107
107
|
expect(subject.represent({}).send(:value_for, :awesome)).to eq(
|
108
|
-
|
109
|
-
|
108
|
+
nested: 'value',
|
109
|
+
another_nested: 'value'
|
110
110
|
)
|
111
111
|
end
|
112
112
|
|
113
113
|
it 'does not represent nested exposures whose conditions are not met' do
|
114
114
|
subject.expose :awesome do
|
115
|
-
subject.expose(:condition_met, if:
|
116
|
-
subject.expose(:condition_not_met, if:
|
115
|
+
subject.expose(:condition_met, if: ->(_, _) { true }) { |_| 'value' }
|
116
|
+
subject.expose(:condition_not_met, if: ->(_, _) { false }) { |_| 'value' }
|
117
117
|
end
|
118
118
|
|
119
119
|
expect(subject.represent({}).send(:value_for, :awesome)).to eq(condition_met: 'value')
|
@@ -129,13 +129,13 @@ describe Grape::Entity do
|
|
129
129
|
end
|
130
130
|
|
131
131
|
expect(subject.represent({}).serializable_hash).to eq(
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
132
|
+
awesome: {
|
133
|
+
nested: 'value',
|
134
|
+
another_nested: 'value',
|
135
|
+
second_level_nested: {
|
136
|
+
deeply_exposed_attr: 'value'
|
137
|
+
}
|
138
|
+
}
|
139
139
|
)
|
140
140
|
end
|
141
141
|
|
@@ -162,22 +162,22 @@ describe Grape::Entity do
|
|
162
162
|
end
|
163
163
|
|
164
164
|
expect(ClassRoom.represent({}).serializable_hash).to eq(
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
165
|
+
parents: [
|
166
|
+
{
|
167
|
+
user: { in_first: 'value' },
|
168
|
+
children: [
|
169
|
+
{ user: { in_first: 'value', user_id: 'value', display_id: 'value' } },
|
170
|
+
{ user: { in_first: 'value', user_id: 'value', display_id: 'value' } }
|
171
|
+
]
|
172
|
+
},
|
173
|
+
{
|
174
|
+
user: { in_first: 'value' },
|
175
|
+
children: [
|
176
|
+
{ user: { in_first: 'value', user_id: 'value', display_id: 'value' } },
|
177
|
+
{ user: { in_first: 'value', user_id: 'value', display_id: 'value' } }
|
178
|
+
]
|
179
|
+
}
|
180
|
+
]
|
181
181
|
)
|
182
182
|
end
|
183
183
|
|
@@ -190,11 +190,14 @@ describe Grape::Entity do
|
|
190
190
|
subject.expose :nested
|
191
191
|
end
|
192
192
|
end
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
193
|
+
expect(subject.represent({}, serializable: true)).to eq(
|
194
|
+
awesome: {
|
195
|
+
nested: 'value'
|
196
|
+
},
|
197
|
+
not_awesome: {
|
198
|
+
nested: nil
|
199
|
+
}
|
200
|
+
)
|
198
201
|
end
|
199
202
|
end
|
200
203
|
end
|
@@ -228,7 +231,7 @@ describe Grape::Entity do
|
|
228
231
|
end
|
229
232
|
|
230
233
|
context 'register formatters' do
|
231
|
-
let(:date_formatter) {
|
234
|
+
let(:date_formatter) { ->(date) { date.strftime('%m/%d/%Y') } }
|
232
235
|
|
233
236
|
it 'registers a formatter' do
|
234
237
|
subject.format_with :timestamp, &date_formatter
|
@@ -259,9 +262,9 @@ describe Grape::Entity do
|
|
259
262
|
end
|
260
263
|
|
261
264
|
it 'formats an exposure with a :format_with lambda that returns a value from the entity instance' do
|
262
|
-
object =
|
265
|
+
object = {}
|
263
266
|
|
264
|
-
subject.expose(:size, format_with:
|
267
|
+
subject.expose(:size, format_with: ->(_value) { self.object.class.to_s })
|
265
268
|
expect(subject.represent(object).send(:value_for, :size)).to eq object.class.to_s
|
266
269
|
end
|
267
270
|
|
@@ -270,7 +273,7 @@ describe Grape::Entity do
|
|
270
273
|
self.object.class.to_s
|
271
274
|
end
|
272
275
|
|
273
|
-
object =
|
276
|
+
object = {}
|
274
277
|
|
275
278
|
subject.expose(:size, format_with: :size_formatter)
|
276
279
|
expect(subject.represent(object).send(:value_for, :size)).to eq object.class.to_s
|
@@ -296,23 +299,12 @@ describe Grape::Entity do
|
|
296
299
|
expect(subject.exposures).to eq(name: {}, email: {})
|
297
300
|
end
|
298
301
|
|
299
|
-
|
300
|
-
|
301
|
-
it 'remove from parent and all child classes that have not locked down their attributes with an .exposures call' do
|
302
|
+
context 'when called from the parent class' do
|
303
|
+
it 'remove from parent and do not remove from child classes' do
|
302
304
|
subject.expose :name, :email
|
303
305
|
child_class = Class.new(subject)
|
304
306
|
subject.unexpose :email
|
305
307
|
|
306
|
-
expect(subject.exposures).to eq(name: {})
|
307
|
-
expect(child_class.exposures).to eq(name: {})
|
308
|
-
end
|
309
|
-
|
310
|
-
it 'remove from parent and do not remove from child classes that have locked down their attributes with an .exposures call' do
|
311
|
-
subject.expose :name, :email
|
312
|
-
child_class = Class.new(subject)
|
313
|
-
child_class.exposures
|
314
|
-
subject.unexpose :email
|
315
|
-
|
316
308
|
expect(subject.exposures).to eq(name: {})
|
317
309
|
expect(child_class.exposures).to eq(name: {}, email: {})
|
318
310
|
end
|
@@ -364,7 +356,7 @@ describe Grape::Entity do
|
|
364
356
|
end
|
365
357
|
|
366
358
|
it 'merges nested :if option' do
|
367
|
-
match_proc =
|
359
|
+
match_proc = ->(_obj, _opts) { true }
|
368
360
|
|
369
361
|
subject.class_eval do
|
370
362
|
# Symbol
|
@@ -383,13 +375,13 @@ describe Grape::Entity do
|
|
383
375
|
end
|
384
376
|
|
385
377
|
expect(subject.exposures[:awesome_thing]).to eq(
|
386
|
-
|
387
|
-
|
378
|
+
if: { awesome: false, less_awesome: true },
|
379
|
+
if_extras: [:awesome, match_proc]
|
388
380
|
)
|
389
381
|
end
|
390
382
|
|
391
383
|
it 'merges nested :unless option' do
|
392
|
-
match_proc =
|
384
|
+
match_proc = ->(_, _) { true }
|
393
385
|
|
394
386
|
subject.class_eval do
|
395
387
|
# Symbol
|
@@ -408,8 +400,8 @@ describe Grape::Entity do
|
|
408
400
|
end
|
409
401
|
|
410
402
|
expect(subject.exposures[:awesome_thing]).to eq(
|
411
|
-
|
412
|
-
|
403
|
+
unless: { awesome: false, less_awesome: true },
|
404
|
+
unless_extras: [:awesome, match_proc]
|
413
405
|
)
|
414
406
|
end
|
415
407
|
|
@@ -433,10 +425,10 @@ describe Grape::Entity do
|
|
433
425
|
end
|
434
426
|
|
435
427
|
it 'overrides nested :proc option' do
|
436
|
-
match_proc =
|
428
|
+
match_proc = ->(_obj, _opts) { 'more awesomer' }
|
437
429
|
|
438
430
|
subject.class_eval do
|
439
|
-
with_options(proc:
|
431
|
+
with_options(proc: ->(_obj, _opts) { 'awesome' }) do
|
440
432
|
expose :awesome_thing, proc: match_proc
|
441
433
|
end
|
442
434
|
end
|
@@ -461,7 +453,7 @@ describe Grape::Entity do
|
|
461
453
|
end
|
462
454
|
|
463
455
|
it 'returns a single entity if called with a hash' do
|
464
|
-
expect(subject.represent(
|
456
|
+
expect(subject.represent({})).to be_kind_of(subject)
|
465
457
|
end
|
466
458
|
|
467
459
|
it 'returns multiple entities if called with a collection' do
|
@@ -506,6 +498,164 @@ describe Grape::Entity do
|
|
506
498
|
subject.represent(Object.new, serializable: true)
|
507
499
|
end.to raise_error(NoMethodError, /missing attribute `awesome'/)
|
508
500
|
end
|
501
|
+
|
502
|
+
context 'with specified fields' do
|
503
|
+
it 'returns only specified fields with only option' do
|
504
|
+
subject.expose(:id, :name, :phone)
|
505
|
+
representation = subject.represent(OpenStruct.new, only: [:id, :name], serializable: true)
|
506
|
+
expect(representation).to eq(id: nil, name: nil)
|
507
|
+
end
|
508
|
+
|
509
|
+
it 'returns all fields except the ones specified in the except option' do
|
510
|
+
subject.expose(:id, :name, :phone)
|
511
|
+
representation = subject.represent(OpenStruct.new, except: [:phone], serializable: true)
|
512
|
+
expect(representation).to eq(id: nil, name: nil)
|
513
|
+
end
|
514
|
+
|
515
|
+
it 'returns only fields specified in the only option and not specified in the except option' do
|
516
|
+
subject.expose(:id, :name, :phone)
|
517
|
+
representation = subject.represent(OpenStruct.new,
|
518
|
+
only: [:name, :phone],
|
519
|
+
except: [:phone], serializable: true)
|
520
|
+
expect(representation).to eq(name: nil)
|
521
|
+
end
|
522
|
+
|
523
|
+
context 'with strings or symbols passed to only and except' do
|
524
|
+
let(:object) { OpenStruct.new(user: {}) }
|
525
|
+
|
526
|
+
before do
|
527
|
+
user_entity = Class.new(Grape::Entity)
|
528
|
+
user_entity.expose(:id, :name, :email)
|
529
|
+
|
530
|
+
subject.expose(:id, :name, :phone, :address)
|
531
|
+
subject.expose(:user, using: user_entity)
|
532
|
+
end
|
533
|
+
|
534
|
+
it 'can specify "only" option attributes as strings' do
|
535
|
+
representation = subject.represent(object, only: ['id', 'name', { 'user' => ['email'] }], serializable: true)
|
536
|
+
expect(representation).to eq(id: nil, name: nil, user: { email: nil })
|
537
|
+
end
|
538
|
+
|
539
|
+
it 'can specify "except" option attributes as strings' do
|
540
|
+
representation = subject.represent(object, except: ['id', 'name', { 'user' => ['email'] }], serializable: true)
|
541
|
+
expect(representation).to eq(phone: nil, address: nil, user: { id: nil, name: nil })
|
542
|
+
end
|
543
|
+
|
544
|
+
it 'can specify "only" option attributes as symbols' do
|
545
|
+
representation = subject.represent(object, only: [:name, :phone, { user: [:name] }], serializable: true)
|
546
|
+
expect(representation).to eq(name: nil, phone: nil, user: { name: nil })
|
547
|
+
end
|
548
|
+
|
549
|
+
it 'can specify "except" option attributes as symbols' do
|
550
|
+
representation = subject.represent(object, except: [:name, :phone, { user: [:name] }], serializable: true)
|
551
|
+
expect(representation).to eq(id: nil, address: nil, user: { id: nil, email: nil })
|
552
|
+
end
|
553
|
+
|
554
|
+
it 'can specify "only" attributes as strings and symbols' do
|
555
|
+
representation = subject.represent(object, only: [:id, 'address', { user: [:id, 'name'] }], serializable: true)
|
556
|
+
expect(representation).to eq(id: nil, address: nil, user: { id: nil, name: nil })
|
557
|
+
end
|
558
|
+
|
559
|
+
it 'can specify "except" attributes as strings and symbols' do
|
560
|
+
representation = subject.represent(object, except: [:id, 'address', { user: [:id, 'name'] }], serializable: true)
|
561
|
+
expect(representation).to eq(name: nil, phone: nil, user: { email: nil })
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
it 'can specify children attributes with only' do
|
566
|
+
user_entity = Class.new(Grape::Entity)
|
567
|
+
user_entity.expose(:id, :name, :email)
|
568
|
+
|
569
|
+
subject.expose(:id, :name, :phone)
|
570
|
+
subject.expose(:user, using: user_entity)
|
571
|
+
|
572
|
+
representation = subject.represent(OpenStruct.new(user: {}), only: [:id, :name, { user: [:name, :email] }], serializable: true)
|
573
|
+
expect(representation).to eq(id: nil, name: nil, user: { name: nil, email: nil })
|
574
|
+
end
|
575
|
+
|
576
|
+
it 'can specify children attributes with except' do
|
577
|
+
user_entity = Class.new(Grape::Entity)
|
578
|
+
user_entity.expose(:id, :name, :email)
|
579
|
+
|
580
|
+
subject.expose(:id, :name, :phone)
|
581
|
+
subject.expose(:user, using: user_entity)
|
582
|
+
|
583
|
+
representation = subject.represent(OpenStruct.new(user: {}), except: [:phone, { user: [:id] }], serializable: true)
|
584
|
+
expect(representation).to eq(id: nil, name: nil, user: { name: nil, email: nil })
|
585
|
+
end
|
586
|
+
|
587
|
+
it 'can specify children attributes with mixed only and except' do
|
588
|
+
user_entity = Class.new(Grape::Entity)
|
589
|
+
user_entity.expose(:id, :name, :email, :address)
|
590
|
+
|
591
|
+
subject.expose(:id, :name, :phone, :mobile_phone)
|
592
|
+
subject.expose(:user, using: user_entity)
|
593
|
+
|
594
|
+
representation = subject.represent(OpenStruct.new(user: {}),
|
595
|
+
only: [:id, :name, :phone, user: [:id, :name, :email]],
|
596
|
+
except: [:phone, { user: [:id] }], serializable: true)
|
597
|
+
expect(representation).to eq(id: nil, name: nil, user: { name: nil, email: nil })
|
598
|
+
end
|
599
|
+
|
600
|
+
context 'specify attribute with exposure condition' do
|
601
|
+
it 'returns only specified fields' do
|
602
|
+
subject.expose(:id)
|
603
|
+
subject.with_options(if: { condition: true }) do
|
604
|
+
subject.expose(:name)
|
605
|
+
end
|
606
|
+
|
607
|
+
representation = subject.represent(OpenStruct.new, condition: true, only: [:id, :name], serializable: true)
|
608
|
+
expect(representation).to eq(id: nil, name: nil)
|
609
|
+
end
|
610
|
+
|
611
|
+
it 'does not return fields specified in the except option' do
|
612
|
+
subject.expose(:id, :phone)
|
613
|
+
subject.with_options(if: { condition: true }) do
|
614
|
+
subject.expose(:name, :mobile_phone)
|
615
|
+
end
|
616
|
+
|
617
|
+
representation = subject.represent(OpenStruct.new, condition: true, except: [:phone, :mobile_phone], serializable: true)
|
618
|
+
expect(representation).to eq(id: nil, name: nil)
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
622
|
+
context 'attribute with alias' do
|
623
|
+
it 'returns only specified fields' do
|
624
|
+
subject.expose(:id)
|
625
|
+
subject.expose(:name, as: :title)
|
626
|
+
|
627
|
+
representation = subject.represent(OpenStruct.new, condition: true, only: [:id, :title], serializable: true)
|
628
|
+
expect(representation).to eq(id: nil, title: nil)
|
629
|
+
end
|
630
|
+
|
631
|
+
it 'does not return fields specified in the except option' do
|
632
|
+
subject.expose(:id)
|
633
|
+
subject.expose(:name, as: :title)
|
634
|
+
subject.expose(:phone, as: :phone_number)
|
635
|
+
|
636
|
+
representation = subject.represent(OpenStruct.new, condition: true, except: [:phone_number], serializable: true)
|
637
|
+
expect(representation).to eq(id: nil, title: nil)
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
context 'attribute that is an entity itself' do
|
642
|
+
it 'returns correctly the children entity attributes' do
|
643
|
+
user_entity = Class.new(Grape::Entity)
|
644
|
+
user_entity.expose(:id, :name, :email)
|
645
|
+
|
646
|
+
nephew_entity = Class.new(Grape::Entity)
|
647
|
+
nephew_entity.expose(:id, :name, :email)
|
648
|
+
|
649
|
+
subject.expose(:id, :name, :phone)
|
650
|
+
subject.expose(:user, using: user_entity)
|
651
|
+
subject.expose(:nephew, using: nephew_entity)
|
652
|
+
|
653
|
+
representation = subject.represent(OpenStruct.new(user: {}),
|
654
|
+
only: [:id, :name, :user], except: [:nephew], serializable: true)
|
655
|
+
expect(representation).to eq(id: nil, name: nil, user: { id: nil, name: nil, email: nil })
|
656
|
+
end
|
657
|
+
end
|
658
|
+
end
|
509
659
|
end
|
510
660
|
|
511
661
|
describe '.present_collection' do
|
@@ -623,6 +773,30 @@ describe Grape::Entity do
|
|
623
773
|
end
|
624
774
|
end
|
625
775
|
end
|
776
|
+
|
777
|
+
context 'inheriting from parent entity' do
|
778
|
+
before(:each) do
|
779
|
+
subject.root 'things', 'thing'
|
780
|
+
end
|
781
|
+
|
782
|
+
it 'inherits single root' do
|
783
|
+
child_class = Class.new(subject)
|
784
|
+
representation = child_class.represent(Object.new)
|
785
|
+
expect(representation).to be_kind_of Hash
|
786
|
+
expect(representation).to have_key 'thing'
|
787
|
+
expect(representation['thing']).to be_kind_of(child_class)
|
788
|
+
end
|
789
|
+
|
790
|
+
it 'inherits array root root' do
|
791
|
+
child_class = Class.new(subject)
|
792
|
+
representation = child_class.represent(4.times.map { Object.new })
|
793
|
+
expect(representation).to be_kind_of Hash
|
794
|
+
expect(representation).to have_key('things')
|
795
|
+
expect(representation['things']).to be_kind_of Array
|
796
|
+
expect(representation['things'].size).to eq 4
|
797
|
+
expect(representation['things'].reject { |r| r.is_a?(child_class) }).to be_empty
|
798
|
+
end
|
799
|
+
end
|
626
800
|
end
|
627
801
|
|
628
802
|
describe '#initialize' do
|
@@ -677,12 +851,23 @@ describe Grape::Entity do
|
|
677
851
|
expect { fresh_class.new(model).serializable_hash }.not_to raise_error
|
678
852
|
end
|
679
853
|
|
680
|
-
it
|
854
|
+
it 'exposes values of private method calls' do
|
855
|
+
some_class = Class.new do
|
856
|
+
define_method :name do
|
857
|
+
true
|
858
|
+
end
|
859
|
+
private :name
|
860
|
+
end
|
861
|
+
fresh_class.expose :name, safe: true
|
862
|
+
expect(fresh_class.new(some_class.new).serializable_hash).to eq(name: true)
|
863
|
+
end
|
864
|
+
|
865
|
+
it "does expose attributes that don't exist on the object as nil" do
|
681
866
|
fresh_class.expose :email, :nonexistent_attribute, :name, safe: true
|
682
867
|
|
683
868
|
res = fresh_class.new(model).serializable_hash
|
684
869
|
expect(res).to have_key :email
|
685
|
-
expect(res).
|
870
|
+
expect(res).to have_key :nonexistent_attribute
|
686
871
|
expect(res).to have_key :name
|
687
872
|
end
|
688
873
|
|
@@ -693,15 +878,15 @@ describe Grape::Entity do
|
|
693
878
|
expect(res).to have_key :name
|
694
879
|
end
|
695
880
|
|
696
|
-
it "does
|
881
|
+
it "does expose attributes that don't exist on the object as nil if criteria is true" do
|
697
882
|
fresh_class.expose :email
|
698
|
-
fresh_class.expose :nonexistent_attribute, safe: true, if:
|
699
|
-
fresh_class.expose :nonexistent_attribute2, safe: true, if:
|
883
|
+
fresh_class.expose :nonexistent_attribute, safe: true, if: ->(_obj, _opts) { false }
|
884
|
+
fresh_class.expose :nonexistent_attribute2, safe: true, if: ->(_obj, _opts) { true }
|
700
885
|
|
701
886
|
res = fresh_class.new(model).serializable_hash
|
702
887
|
expect(res).to have_key :email
|
703
888
|
expect(res).not_to have_key :nonexistent_attribute
|
704
|
-
expect(res).
|
889
|
+
expect(res).to have_key :nonexistent_attribute2
|
705
890
|
end
|
706
891
|
end
|
707
892
|
|
@@ -720,9 +905,9 @@ describe Grape::Entity do
|
|
720
905
|
end
|
721
906
|
|
722
907
|
it 'does not expose attributes that are generated by a block but have not passed criteria' do
|
723
|
-
fresh_class.expose :nonexistent_attribute,
|
724
|
-
|
725
|
-
|
908
|
+
fresh_class.expose :nonexistent_attribute,
|
909
|
+
proc: ->(_model, _opts) { 'I exist, but it is not yet my time to shine' },
|
910
|
+
if: ->(_model, _opts) { false }
|
726
911
|
res = fresh_class.new(model).serializable_hash
|
727
912
|
expect(res).not_to have_key :nonexistent_attribute
|
728
913
|
end
|
@@ -742,9 +927,9 @@ describe Grape::Entity do
|
|
742
927
|
end
|
743
928
|
|
744
929
|
it 'does not expose attributes that are generated by a block but have not passed criteria' do
|
745
|
-
fresh_class.expose :nonexistent_attribute,
|
746
|
-
|
747
|
-
|
930
|
+
fresh_class.expose :nonexistent_attribute,
|
931
|
+
proc: ->(_, _) { 'I exist, but it is not yet my time to shine' },
|
932
|
+
if: ->(_, _) { false }
|
748
933
|
res = fresh_class.new(model).serializable_hash
|
749
934
|
expect(res).not_to have_key :nonexistent_attribute
|
750
935
|
end
|
@@ -823,7 +1008,7 @@ describe Grape::Entity do
|
|
823
1008
|
date.strftime('%m/%d/%Y')
|
824
1009
|
end
|
825
1010
|
|
826
|
-
expose :fantasies, format_with:
|
1011
|
+
expose :fantasies, format_with: ->(f) { f.reverse }
|
827
1012
|
end
|
828
1013
|
end
|
829
1014
|
|
@@ -1071,6 +1256,46 @@ describe Grape::Entity do
|
|
1071
1256
|
|
1072
1257
|
expect(subject.documentation).to eq(label: doc, email: doc)
|
1073
1258
|
end
|
1259
|
+
|
1260
|
+
context 'inherited documentation' do
|
1261
|
+
it 'returns documentation from ancestor' do
|
1262
|
+
doc = { type: 'foo', desc: 'bar' }
|
1263
|
+
fresh_class.expose :name, documentation: doc
|
1264
|
+
child_class = Class.new(fresh_class)
|
1265
|
+
child_class.expose :email, documentation: doc
|
1266
|
+
|
1267
|
+
expect(fresh_class.documentation).to eq(name: doc)
|
1268
|
+
expect(child_class.documentation).to eq(name: doc, email: doc)
|
1269
|
+
end
|
1270
|
+
|
1271
|
+
it 'obeys unexposed attributes in subclass' do
|
1272
|
+
doc = { type: 'foo', desc: 'bar' }
|
1273
|
+
fresh_class.expose :name, documentation: doc
|
1274
|
+
fresh_class.expose :email, documentation: doc
|
1275
|
+
child_class = Class.new(fresh_class)
|
1276
|
+
child_class.unexpose :email
|
1277
|
+
|
1278
|
+
expect(fresh_class.documentation).to eq(name: doc, email: doc)
|
1279
|
+
expect(child_class.documentation).to eq(name: doc)
|
1280
|
+
end
|
1281
|
+
|
1282
|
+
it 'obeys re-exposed attributes in subclass' do
|
1283
|
+
doc = { type: 'foo', desc: 'bar' }
|
1284
|
+
fresh_class.expose :name, documentation: doc
|
1285
|
+
fresh_class.expose :email, documentation: doc
|
1286
|
+
|
1287
|
+
child_class = Class.new(fresh_class)
|
1288
|
+
child_class.unexpose :email
|
1289
|
+
|
1290
|
+
nephew_class = Class.new(child_class)
|
1291
|
+
new_doc = { type: 'todler', descr: '???' }
|
1292
|
+
nephew_class.expose :email, documentation: new_doc
|
1293
|
+
|
1294
|
+
expect(fresh_class.documentation).to eq(name: doc, email: doc)
|
1295
|
+
expect(child_class.documentation).to eq(name: doc)
|
1296
|
+
expect(nephew_class.documentation).to eq(name: doc, email: new_doc)
|
1297
|
+
end
|
1298
|
+
end
|
1074
1299
|
end
|
1075
1300
|
|
1076
1301
|
describe '#key_for' do
|
@@ -1120,7 +1345,7 @@ describe Grape::Entity do
|
|
1120
1345
|
end
|
1121
1346
|
|
1122
1347
|
it 'only passes through proc :if exposure if it returns truthy value' do
|
1123
|
-
exposure_options = { if:
|
1348
|
+
exposure_options = { if: ->(_, opts) { opts[:true] } }
|
1124
1349
|
|
1125
1350
|
expect(subject.send(:conditions_met?, exposure_options, true: false)).to be false
|
1126
1351
|
expect(subject.send(:conditions_met?, exposure_options, true: true)).to be true
|
@@ -1138,7 +1363,7 @@ describe Grape::Entity do
|
|
1138
1363
|
end
|
1139
1364
|
|
1140
1365
|
it 'only passes through proc :unless exposure if it returns falsy value' do
|
1141
|
-
exposure_options = { unless:
|
1366
|
+
exposure_options = { unless: ->(_, opts) { opts[:true] == true } }
|
1142
1367
|
|
1143
1368
|
expect(subject.send(:conditions_met?, exposure_options, true: false)).to be true
|
1144
1369
|
expect(subject.send(:conditions_met?, exposure_options, true: true)).to be false
|