grape-entity 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/README.md +36 -2
- data/lib/grape_entity/entity.rb +81 -12
- data/lib/grape_entity/version.rb +1 -1
- data/spec/grape_entity/entity_spec.rb +227 -196
- data/spec/spec_helper.rb +4 -0
- metadata +19 -41
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bca27e644c8d862751cbb573d3da20ec58fa9a1a
|
4
|
+
data.tar.gz: 40aa499604d5a7941fc13016c58c9a2fda9de787
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b02bedc0adc756dec9fb93c0ae527eb4251e21882aedefb30f3f973fd867ee9589a61702d0464ae69366ea4fc27f5e42ce382ea9ec247b347ebeab2c3c817713
|
7
|
+
data.tar.gz: c175aad11e6c88bfbd10c551a3f1cd0381753b918bc901f9786676f03558dc6e75d369e25ebc3aad45ed780ecf4f78d2a3e3627aa519e0824b29e11ec248794f
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
0.4.4 (2014-08-17)
|
2
|
+
==================
|
3
|
+
|
4
|
+
* [#85](https://github.com/intridea/grape-entity/pull/85): Added `present_collection` to indicate that an `Entity` presents an entire Collection - [@dspaeth-faber](https://github.com/dspaeth-faber).
|
5
|
+
* [#85](https://guthub.com/intridea/grape-entity/pull/85): Hashes can now be passed as object to be presented and the `Hash` keys can be referenced by expose - [@dspaeth-faber](https://github.com/dspaeth-faber).
|
6
|
+
|
1
7
|
0.4.3 (2014-06-12)
|
2
8
|
==================
|
3
9
|
|
data/README.md
CHANGED
@@ -63,6 +63,13 @@ Define a list of fields that will always be exposed.
|
|
63
63
|
expose :user_name, :ip
|
64
64
|
```
|
65
65
|
|
66
|
+
The field lookup takes several steps
|
67
|
+
|
68
|
+
* first try `entity-instance.exposure`
|
69
|
+
* next try `object.exposure`
|
70
|
+
* next try `object.fetch(exposure)`
|
71
|
+
* last raise an Exception
|
72
|
+
|
66
73
|
#### Exposing with a Presenter
|
67
74
|
|
68
75
|
Don't derive your model classes from `Grape::Entity`, expose them using a presenter.
|
@@ -119,6 +126,20 @@ root 'users', 'user'
|
|
119
126
|
expose :id, :name, ...
|
120
127
|
```
|
121
128
|
|
129
|
+
By default every object of a collection is wrapped into an instance of your `Entity` class.
|
130
|
+
You can override this behavior and wrapp the hole collection into one instance of your `Entity`
|
131
|
+
class.
|
132
|
+
|
133
|
+
As example:
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
|
137
|
+
present_collection true, :collection_name # `collection_name` is optional and defaults to `items`
|
138
|
+
expose :collection_name, using: API:Items
|
139
|
+
|
140
|
+
|
141
|
+
```
|
142
|
+
|
122
143
|
#### Runtime Exposure
|
123
144
|
|
124
145
|
Use a block or a `Proc` to evaluate exposure at runtime. The supplied block or
|
@@ -151,6 +172,20 @@ private
|
|
151
172
|
end
|
152
173
|
```
|
153
174
|
|
175
|
+
You have always access to the presented instance with `object`
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
class ExampleEntity < Grape::Entity
|
179
|
+
expose :formatted_value
|
180
|
+
# ...
|
181
|
+
private
|
182
|
+
|
183
|
+
def formatted_value
|
184
|
+
"+ X #{object.value}"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
154
189
|
#### Aliases
|
155
190
|
|
156
191
|
Expose under a different name with `:as`.
|
@@ -216,8 +251,7 @@ The above will automatically create a `Status::Entity` class and define properti
|
|
216
251
|
|
217
252
|
### Using Entities
|
218
253
|
|
219
|
-
With Grape, once an entity is defined, it can be used within endpoints, by calling `present`. The `present` method accepts two arguments, the object to be presented and the options associated with it. The options hash must always include `:with`, which defines the entity to expose.
|
220
|
-
|
254
|
+
With Grape, once an entity is defined, it can be used within endpoints, by calling `present`. The `present` method accepts two arguments, the `object` to be presented and the `options` associated with it. The options hash must always include `:with`, which defines the entity to expose.
|
221
255
|
If the entity includes documentation it can be included in an endpoint's description.
|
222
256
|
|
223
257
|
```ruby
|
data/lib/grape_entity/entity.rb
CHANGED
@@ -329,6 +329,62 @@ module Grape
|
|
329
329
|
@root = singular
|
330
330
|
end
|
331
331
|
|
332
|
+
# This allows you to present a collection of objects.
|
333
|
+
#
|
334
|
+
# @param present_collection [true or false] when true all objects will be available as
|
335
|
+
# items in your presenter instead of wrapping each object in an instance of your presenter.
|
336
|
+
# When false (default) every object in a collection to present will be wrapped separately
|
337
|
+
# into an instance of your presenter.
|
338
|
+
# @param collection_name [Symbol] the name of the collection accessor in your entity object.
|
339
|
+
# Default :items
|
340
|
+
#
|
341
|
+
# @example Entity Definition
|
342
|
+
#
|
343
|
+
# module API
|
344
|
+
# module Entities
|
345
|
+
# class User < Grape::Entity
|
346
|
+
# expose :id
|
347
|
+
# end
|
348
|
+
#
|
349
|
+
# class Users < Grape::Entity
|
350
|
+
# present_collection true
|
351
|
+
# expose :items, as: 'users', using: API::Entities::Users
|
352
|
+
# expose :version, documentation: { type: 'string',
|
353
|
+
# desc: 'actual api version',
|
354
|
+
# required: true }
|
355
|
+
#
|
356
|
+
# def version
|
357
|
+
# options[:version]
|
358
|
+
# end
|
359
|
+
# end
|
360
|
+
# end
|
361
|
+
# end
|
362
|
+
#
|
363
|
+
# @example Usage in the API Layer
|
364
|
+
#
|
365
|
+
# module API
|
366
|
+
# class Users < Grape::API
|
367
|
+
# version 'v2'
|
368
|
+
#
|
369
|
+
# # this will render { "users" : [ { "id" : "1" }, { "id" : "2" } ], "version" : "v2" }
|
370
|
+
# get '/users' do
|
371
|
+
# @users = User.all
|
372
|
+
# present @users, with: API::Entities::Users
|
373
|
+
# end
|
374
|
+
#
|
375
|
+
# # this will render { "user" : { "id" : "1" } }
|
376
|
+
# get '/users/:id' do
|
377
|
+
# @user = User.find(params[:id])
|
378
|
+
# present @user, with: API::Entities::User
|
379
|
+
# end
|
380
|
+
# end
|
381
|
+
# end
|
382
|
+
#
|
383
|
+
def self.present_collection(present_collection = false, collection_name = :items)
|
384
|
+
@present_collection = present_collection
|
385
|
+
@collection_name = collection_name
|
386
|
+
end
|
387
|
+
|
332
388
|
# This convenience method allows you to instantiate one or more entities by
|
333
389
|
# passing either a singular or collection of objects. Each object will be
|
334
390
|
# initialized with the same options. If an array of objects is passed in,
|
@@ -339,27 +395,34 @@ module Grape
|
|
339
395
|
# @param options [Hash] Options that will be passed through to each entity
|
340
396
|
# representation.
|
341
397
|
#
|
342
|
-
# @option options :root [String] override the default root name set for the entity.
|
398
|
+
# @option options :root [String or false] override the default root name set for the entity.
|
343
399
|
# Pass nil or false to represent the object or objects with no root name
|
344
400
|
# even if one is defined for the entity.
|
401
|
+
# @option options :serializable [true or false] when true a serializable Hash will be returned
|
402
|
+
#
|
345
403
|
def self.represent(objects, options = {})
|
346
|
-
if objects.respond_to?(:to_ary)
|
347
|
-
|
348
|
-
inner =
|
404
|
+
if objects.respond_to?(:to_ary) && ! @present_collection
|
405
|
+
root_element = @collection_root
|
406
|
+
inner = objects.to_ary.map { |object| new(object, { collection: true }.merge(options)).presented }
|
349
407
|
else
|
350
|
-
|
351
|
-
|
408
|
+
objects = { @collection_name => objects } if @present_collection
|
409
|
+
root_element = @root
|
410
|
+
inner = new(objects, options).presented
|
352
411
|
end
|
353
412
|
|
354
|
-
root_element = if options.key?(:root)
|
355
|
-
options[:root]
|
356
|
-
else
|
357
|
-
objects.respond_to?(:to_ary) ? @collection_root : @root
|
358
|
-
end
|
413
|
+
root_element = options[:root] if options.key?(:root)
|
359
414
|
|
360
415
|
root_element ? { root_element => inner } : inner
|
361
416
|
end
|
362
417
|
|
418
|
+
def presented
|
419
|
+
if options[:serializable]
|
420
|
+
serializable_hash
|
421
|
+
else
|
422
|
+
self
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
363
426
|
def initialize(object, options = {})
|
364
427
|
@object, @options = object, options
|
365
428
|
end
|
@@ -486,7 +549,13 @@ module Grape
|
|
486
549
|
if respond_to?(name, true)
|
487
550
|
send(name)
|
488
551
|
else
|
489
|
-
object.
|
552
|
+
if object.respond_to?(name, true)
|
553
|
+
object.send(name)
|
554
|
+
elsif object.respond_to?(:fetch, true)
|
555
|
+
object.fetch(name)
|
556
|
+
else
|
557
|
+
raise ArgumentError
|
558
|
+
end
|
490
559
|
end
|
491
560
|
end
|
492
561
|
|
data/lib/grape_entity/version.rb
CHANGED
@@ -11,12 +11,12 @@ describe Grape::Entity do
|
|
11
11
|
context 'multiple attributes' do
|
12
12
|
it 'is able to add multiple exposed attributes with a single call' do
|
13
13
|
subject.expose :name, :email, :location
|
14
|
-
subject.exposures.size.
|
14
|
+
expect(subject.exposures.size).to eq 3
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'sets the same options for all exposures passed' do
|
18
18
|
subject.expose :name, :email, :location, documentation: true
|
19
|
-
subject.exposures.values.each { |v| v.
|
19
|
+
subject.exposures.values.each { |v| expect(v).to eq(documentation: true) }
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -62,22 +62,22 @@ describe Grape::Entity do
|
|
62
62
|
|
63
63
|
object = EntitySpec::SomeObject1.new
|
64
64
|
value = subject.represent(object).send(:value_for, :bogus)
|
65
|
-
value.
|
65
|
+
expect(value).to be_instance_of EntitySpec::BogusEntity
|
66
66
|
|
67
67
|
prop1 = value.send(:value_for, :prop1)
|
68
|
-
prop1.
|
68
|
+
expect(prop1).to eq 'MODIFIED 2'
|
69
69
|
end
|
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
73
|
block = lambda { |_| true }
|
74
74
|
subject.expose :name, using: 'Awesome', &block
|
75
|
-
subject.exposures[:name].
|
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
|
-
subject.represent(Hash.new).send(:value_for, :size).
|
80
|
+
expect(subject.represent(Hash.new).send(:value_for, :size)).to be_an_instance_of fresh_class
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -90,12 +90,12 @@ describe Grape::Entity do
|
|
90
90
|
subject.expose :another_nested, using: 'Awesome'
|
91
91
|
end
|
92
92
|
|
93
|
-
subject.exposures.
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
93
|
+
expect(subject.exposures).to eq(
|
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
|
+
)
|
99
99
|
end
|
100
100
|
|
101
101
|
it 'represents the exposure as a hash of its nested exposures' do
|
@@ -104,10 +104,10 @@ describe Grape::Entity do
|
|
104
104
|
subject.expose(:another_nested) { |_| 'value' }
|
105
105
|
end
|
106
106
|
|
107
|
-
subject.represent({}).send(:value_for, :awesome).
|
108
|
-
|
109
|
-
|
110
|
-
|
107
|
+
expect(subject.represent({}).send(:value_for, :awesome)).to eq(
|
108
|
+
nested: 'value',
|
109
|
+
another_nested: 'value'
|
110
|
+
)
|
111
111
|
end
|
112
112
|
|
113
113
|
it 'does not represent attributes, declared inside nested exposure, outside of it' do
|
@@ -119,15 +119,15 @@ describe Grape::Entity do
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
subject.represent({}).serializable_hash.
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
122
|
+
expect(subject.represent({}).serializable_hash).to eq(
|
123
|
+
awesome: {
|
124
|
+
nested: 'value',
|
125
|
+
another_nested: 'value',
|
126
|
+
second_level_nested: {
|
127
|
+
deeply_exposed_attr: 'value'
|
128
|
+
}
|
129
|
+
}
|
130
|
+
)
|
131
131
|
end
|
132
132
|
|
133
133
|
it 'complex nested attributes' do
|
@@ -152,24 +152,24 @@ describe Grape::Entity do
|
|
152
152
|
expose(:children, using: 'Student') { |_| [{}, {}] }
|
153
153
|
end
|
154
154
|
|
155
|
-
ClassRoom.represent({}).serializable_hash.
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
155
|
+
expect(ClassRoom.represent({}).serializable_hash).to eq(
|
156
|
+
parents: [
|
157
|
+
{
|
158
|
+
user: { in_first: 'value' },
|
159
|
+
children: [
|
160
|
+
{ user: { in_first: 'value', user_id: 'value', display_id: 'value' } },
|
161
|
+
{ user: { in_first: 'value', user_id: 'value', display_id: 'value' } }
|
162
|
+
]
|
163
|
+
},
|
164
|
+
{
|
165
|
+
user: { in_first: 'value' },
|
166
|
+
children: [
|
167
|
+
{ user: { in_first: 'value', user_id: 'value', display_id: 'value' } },
|
168
|
+
{ user: { in_first: 'value', user_id: 'value', display_id: 'value' } }
|
169
|
+
]
|
170
|
+
}
|
171
|
+
]
|
172
|
+
)
|
173
173
|
end
|
174
174
|
|
175
175
|
it 'is safe if its nested exposures are safe' do
|
@@ -184,8 +184,8 @@ describe Grape::Entity do
|
|
184
184
|
|
185
185
|
valid_keys = subject.represent({}).valid_exposures.keys
|
186
186
|
|
187
|
-
valid_keys.include?(:awesome).
|
188
|
-
valid_keys.include?(:not_awesome).
|
187
|
+
expect(valid_keys.include?(:awesome)).to be true
|
188
|
+
expect(valid_keys.include?(:not_awesome)).to be false
|
189
189
|
end
|
190
190
|
end
|
191
191
|
end
|
@@ -195,7 +195,7 @@ describe Grape::Entity do
|
|
195
195
|
subject.expose :name, :email
|
196
196
|
child_class = Class.new(subject)
|
197
197
|
|
198
|
-
child_class.exposures.
|
198
|
+
expect(child_class.exposures).to eq(subject.exposures)
|
199
199
|
end
|
200
200
|
|
201
201
|
it 'returns exposures from multiple ancestor' do
|
@@ -203,7 +203,7 @@ describe Grape::Entity do
|
|
203
203
|
parent_class = Class.new(subject)
|
204
204
|
child_class = Class.new(parent_class)
|
205
205
|
|
206
|
-
child_class.exposures.
|
206
|
+
expect(child_class.exposures).to eq(subject.exposures)
|
207
207
|
end
|
208
208
|
|
209
209
|
it 'returns descendant exposures as a priority' do
|
@@ -213,8 +213,8 @@ describe Grape::Entity do
|
|
213
213
|
'foo'
|
214
214
|
end
|
215
215
|
|
216
|
-
subject.exposures[:name].
|
217
|
-
child_class.exposures[:name].
|
216
|
+
expect(subject.exposures[:name]).not_to have_key :proc
|
217
|
+
expect(child_class.exposures[:name]).to have_key :proc
|
218
218
|
end
|
219
219
|
end
|
220
220
|
|
@@ -224,14 +224,14 @@ describe Grape::Entity do
|
|
224
224
|
it 'registers a formatter' do
|
225
225
|
subject.format_with :timestamp, &date_formatter
|
226
226
|
|
227
|
-
subject.formatters[:timestamp].
|
227
|
+
expect(subject.formatters[:timestamp]).not_to be_nil
|
228
228
|
end
|
229
229
|
|
230
230
|
it 'inherits formatters from ancestors' do
|
231
231
|
subject.format_with :timestamp, &date_formatter
|
232
232
|
child_class = Class.new(subject)
|
233
233
|
|
234
|
-
child_class.formatters.
|
234
|
+
expect(child_class.formatters).to eq subject.formatters
|
235
235
|
end
|
236
236
|
|
237
237
|
it 'does not allow registering a formatter without a block' do
|
@@ -246,14 +246,14 @@ describe Grape::Entity do
|
|
246
246
|
subject.expose :birthday, format_with: :timestamp
|
247
247
|
|
248
248
|
model = { birthday: Time.gm(2012, 2, 27) }
|
249
|
-
subject.new(double(model)).as_json[:birthday].
|
249
|
+
expect(subject.new(double(model)).as_json[:birthday]).to eq '02/27/2012'
|
250
250
|
end
|
251
251
|
|
252
252
|
it 'formats an exposure with a :format_with lambda that returns a value from the entity instance' do
|
253
253
|
object = Hash.new
|
254
254
|
|
255
255
|
subject.expose(:size, format_with: lambda { |_value| self.object.class.to_s })
|
256
|
-
subject.represent(object).send(:value_for, :size).
|
256
|
+
expect(subject.represent(object).send(:value_for, :size)).to eq object.class.to_s
|
257
257
|
end
|
258
258
|
|
259
259
|
it 'formats an exposure with a :format_with symbol that returns a value from the entity instance' do
|
@@ -264,7 +264,7 @@ describe Grape::Entity do
|
|
264
264
|
object = Hash.new
|
265
265
|
|
266
266
|
subject.expose(:size, format_with: :size_formatter)
|
267
|
-
subject.represent(object).send(:value_for, :size).
|
267
|
+
expect(subject.represent(object).send(:value_for, :size)).to eq object.class.to_s
|
268
268
|
end
|
269
269
|
end
|
270
270
|
end
|
@@ -287,7 +287,7 @@ describe Grape::Entity do
|
|
287
287
|
end
|
288
288
|
end
|
289
289
|
|
290
|
-
subject.exposures[:awesome_thing].
|
290
|
+
expect(subject.exposures[:awesome_thing]).to eq(if: { awesome: true }, using: 'Awesome')
|
291
291
|
end
|
292
292
|
|
293
293
|
it 'allows for nested .with_options' do
|
@@ -299,7 +299,7 @@ describe Grape::Entity do
|
|
299
299
|
end
|
300
300
|
end
|
301
301
|
|
302
|
-
subject.exposures[:awesome_thing].
|
302
|
+
expect(subject.exposures[:awesome_thing]).to eq(if: { awesome: true }, using: 'Something')
|
303
303
|
end
|
304
304
|
|
305
305
|
it 'overrides nested :as option' do
|
@@ -309,7 +309,7 @@ describe Grape::Entity do
|
|
309
309
|
end
|
310
310
|
end
|
311
311
|
|
312
|
-
subject.exposures[:awesome_thing].
|
312
|
+
expect(subject.exposures[:awesome_thing]).to eq(as: :extra_smooth)
|
313
313
|
end
|
314
314
|
|
315
315
|
it 'merges nested :if option' do
|
@@ -331,10 +331,10 @@ describe Grape::Entity do
|
|
331
331
|
end
|
332
332
|
end
|
333
333
|
|
334
|
-
subject.exposures[:awesome_thing].
|
335
|
-
|
336
|
-
|
337
|
-
|
334
|
+
expect(subject.exposures[:awesome_thing]).to eq(
|
335
|
+
if: { awesome: false, less_awesome: true },
|
336
|
+
if_extras: [:awesome, match_proc]
|
337
|
+
)
|
338
338
|
end
|
339
339
|
|
340
340
|
it 'merges nested :unless option' do
|
@@ -356,10 +356,10 @@ describe Grape::Entity do
|
|
356
356
|
end
|
357
357
|
end
|
358
358
|
|
359
|
-
subject.exposures[:awesome_thing].
|
360
|
-
|
361
|
-
|
362
|
-
|
359
|
+
expect(subject.exposures[:awesome_thing]).to eq(
|
360
|
+
unless: { awesome: false, less_awesome: true },
|
361
|
+
unless_extras: [:awesome, match_proc]
|
362
|
+
)
|
363
363
|
end
|
364
364
|
|
365
365
|
it 'overrides nested :using option' do
|
@@ -369,7 +369,7 @@ describe Grape::Entity do
|
|
369
369
|
end
|
370
370
|
end
|
371
371
|
|
372
|
-
subject.exposures[:awesome_thing].
|
372
|
+
expect(subject.exposures[:awesome_thing]).to eq(using: 'SomethingElse')
|
373
373
|
end
|
374
374
|
|
375
375
|
it 'aliases :with option to :using option' do
|
@@ -378,7 +378,7 @@ describe Grape::Entity do
|
|
378
378
|
expose :awesome_thing, with: 'SomethingElse'
|
379
379
|
end
|
380
380
|
end
|
381
|
-
subject.exposures[:awesome_thing].
|
381
|
+
expect(subject.exposures[:awesome_thing]).to eq(using: 'SomethingElse')
|
382
382
|
end
|
383
383
|
|
384
384
|
it 'overrides nested :proc option' do
|
@@ -390,7 +390,7 @@ describe Grape::Entity do
|
|
390
390
|
end
|
391
391
|
end
|
392
392
|
|
393
|
-
subject.exposures[:awesome_thing].
|
393
|
+
expect(subject.exposures[:awesome_thing]).to eq(proc: match_proc)
|
394
394
|
end
|
395
395
|
|
396
396
|
it 'overrides nested :documentation option' do
|
@@ -400,41 +400,72 @@ describe Grape::Entity do
|
|
400
400
|
end
|
401
401
|
end
|
402
402
|
|
403
|
-
subject.exposures[:awesome_thing].
|
403
|
+
expect(subject.exposures[:awesome_thing]).to eq(documentation: { desc: 'Other description.' })
|
404
404
|
end
|
405
405
|
end
|
406
406
|
|
407
407
|
describe '.represent' do
|
408
408
|
it 'returns a single entity if called with one object' do
|
409
|
-
subject.represent(Object.new).
|
409
|
+
expect(subject.represent(Object.new)).to be_kind_of(subject)
|
410
410
|
end
|
411
411
|
|
412
412
|
it 'returns a single entity if called with a hash' do
|
413
|
-
subject.represent(Hash.new).
|
413
|
+
expect(subject.represent(Hash.new)).to be_kind_of(subject)
|
414
414
|
end
|
415
415
|
|
416
416
|
it 'returns multiple entities if called with a collection' do
|
417
417
|
representation = subject.represent(4.times.map { Object.new })
|
418
|
-
representation.
|
419
|
-
representation.size.
|
420
|
-
representation.reject { |r| r.kind_of?(subject) }.
|
418
|
+
expect(representation).to be_kind_of Array
|
419
|
+
expect(representation.size).to eq(4)
|
420
|
+
expect(representation.reject { |r| r.kind_of?(subject) }).to be_empty
|
421
421
|
end
|
422
422
|
|
423
423
|
it 'adds the collection: true option if called with a collection' do
|
424
424
|
representation = subject.represent(4.times.map { Object.new })
|
425
|
-
representation.each { |r| r.options[:collection].
|
425
|
+
representation.each { |r| expect(r.options[:collection]).to be true }
|
426
426
|
end
|
427
427
|
|
428
428
|
it 'returns a serialized hash of a single object if serializable: true' do
|
429
429
|
subject.expose(:awesome) { |_| true }
|
430
430
|
representation = subject.represent(Object.new, serializable: true)
|
431
|
-
representation.
|
431
|
+
expect(representation).to eq(awesome: true)
|
432
432
|
end
|
433
433
|
|
434
434
|
it 'returns a serialized array of hashes of multiple objects if serializable: true' do
|
435
435
|
subject.expose(:awesome) { |_| true }
|
436
436
|
representation = subject.represent(2.times.map { Object.new }, serializable: true)
|
437
|
-
representation.
|
437
|
+
expect(representation).to eq([{ awesome: true }, { awesome: true }])
|
438
|
+
end
|
439
|
+
|
440
|
+
it 'returns a serialized hash of a hash' do
|
441
|
+
subject.expose(:awesome)
|
442
|
+
representation = subject.represent({ awesome: true }, serializable: true)
|
443
|
+
expect(representation).to eq(awesome: true)
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
describe '.present_collection' do
|
448
|
+
it 'make the objects accessible' do
|
449
|
+
subject.present_collection true
|
450
|
+
subject.expose :items
|
451
|
+
|
452
|
+
representation = subject.represent(4.times.map { Object.new })
|
453
|
+
expect(representation).to be_kind_of(subject)
|
454
|
+
expect(representation.object).to be_kind_of(Hash)
|
455
|
+
expect(representation.object).to have_key :items
|
456
|
+
expect(representation.object[:items]).to be_kind_of Array
|
457
|
+
expect(representation.object[:items].size).to be 4
|
458
|
+
end
|
459
|
+
|
460
|
+
it 'serializes items with my root name' do
|
461
|
+
subject.present_collection true, :my_items
|
462
|
+
subject.expose :my_items
|
463
|
+
|
464
|
+
representation = subject.represent(4.times.map { Object.new }, serializable: true)
|
465
|
+
expect(representation).to be_kind_of(Hash)
|
466
|
+
expect(representation).to have_key :my_items
|
467
|
+
expect(representation[:my_items]).to be_kind_of Array
|
468
|
+
expect(representation[:my_items].size).to be 4
|
438
469
|
end
|
439
470
|
end
|
440
471
|
|
@@ -447,37 +478,37 @@ describe Grape::Entity do
|
|
447
478
|
context 'with a single object' do
|
448
479
|
it 'allows a root element name to be specified' do
|
449
480
|
representation = subject.represent(Object.new)
|
450
|
-
representation.
|
451
|
-
representation.
|
452
|
-
representation['thing'].
|
481
|
+
expect(representation).to be_kind_of Hash
|
482
|
+
expect(representation).to have_key 'thing'
|
483
|
+
expect(representation['thing']).to be_kind_of(subject)
|
453
484
|
end
|
454
485
|
end
|
455
486
|
|
456
487
|
context 'with an array of objects' do
|
457
488
|
it 'allows a root element name to be specified' do
|
458
489
|
representation = subject.represent(4.times.map { Object.new })
|
459
|
-
representation.
|
460
|
-
representation.
|
461
|
-
representation['things'].
|
462
|
-
representation['things'].size.
|
463
|
-
representation['things'].reject { |r| r.kind_of?(subject) }.
|
490
|
+
expect(representation).to be_kind_of Hash
|
491
|
+
expect(representation).to have_key 'things'
|
492
|
+
expect(representation['things']).to be_kind_of Array
|
493
|
+
expect(representation['things'].size).to eq 4
|
494
|
+
expect(representation['things'].reject { |r| r.kind_of?(subject) }).to be_empty
|
464
495
|
end
|
465
496
|
end
|
466
497
|
|
467
498
|
context 'it can be overridden' do
|
468
499
|
it 'can be disabled' do
|
469
500
|
representation = subject.represent(4.times.map { Object.new }, root: false)
|
470
|
-
representation.
|
471
|
-
representation.size.
|
472
|
-
representation.reject { |r| r.kind_of?(subject) }.
|
501
|
+
expect(representation).to be_kind_of Array
|
502
|
+
expect(representation.size).to eq 4
|
503
|
+
expect(representation.reject { |r| r.kind_of?(subject) }).to be_empty
|
473
504
|
end
|
474
505
|
it 'can use a different name' do
|
475
506
|
representation = subject.represent(4.times.map { Object.new }, root: 'others')
|
476
|
-
representation.
|
477
|
-
representation.
|
478
|
-
representation['others'].
|
479
|
-
representation['others'].size.
|
480
|
-
representation['others'].reject { |r| r.kind_of?(subject) }.
|
507
|
+
expect(representation).to be_kind_of Hash
|
508
|
+
expect(representation).to have_key 'others'
|
509
|
+
expect(representation['others']).to be_kind_of Array
|
510
|
+
expect(representation['others'].size).to eq 4
|
511
|
+
expect(representation['others'].reject { |r| r.kind_of?(subject) }).to be_empty
|
481
512
|
end
|
482
513
|
end
|
483
514
|
end
|
@@ -490,18 +521,18 @@ describe Grape::Entity do
|
|
490
521
|
context 'with a single object' do
|
491
522
|
it 'allows a root element name to be specified' do
|
492
523
|
representation = subject.represent(Object.new)
|
493
|
-
representation.
|
494
|
-
representation.
|
495
|
-
representation['thing'].
|
524
|
+
expect(representation).to be_kind_of Hash
|
525
|
+
expect(representation).to have_key 'thing'
|
526
|
+
expect(representation['thing']).to be_kind_of(subject)
|
496
527
|
end
|
497
528
|
end
|
498
529
|
|
499
530
|
context 'with an array of objects' do
|
500
531
|
it 'allows a root element name to be specified' do
|
501
532
|
representation = subject.represent(4.times.map { Object.new })
|
502
|
-
representation.
|
503
|
-
representation.size.
|
504
|
-
representation.reject { |r| r.kind_of?(subject) }.
|
533
|
+
expect(representation).to be_kind_of Array
|
534
|
+
expect(representation.size).to eq 4
|
535
|
+
expect(representation.reject { |r| r.kind_of?(subject) }).to be_empty
|
505
536
|
end
|
506
537
|
end
|
507
538
|
end
|
@@ -513,18 +544,18 @@ describe Grape::Entity do
|
|
513
544
|
|
514
545
|
context 'with a single object' do
|
515
546
|
it 'allows a root element name to be specified' do
|
516
|
-
subject.represent(Object.new).
|
547
|
+
expect(subject.represent(Object.new)).to be_kind_of(subject)
|
517
548
|
end
|
518
549
|
end
|
519
550
|
|
520
551
|
context 'with an array of objects' do
|
521
552
|
it 'allows a root element name to be specified' do
|
522
553
|
representation = subject.represent(4.times.map { Object.new })
|
523
|
-
representation.
|
524
|
-
representation.
|
525
|
-
representation['things'].
|
526
|
-
representation['things'].size.
|
527
|
-
representation['things'].reject { |r| r.kind_of?(subject) }.
|
554
|
+
expect(representation).to be_kind_of Hash
|
555
|
+
expect(representation).to have_key('things')
|
556
|
+
expect(representation['things']).to be_kind_of Array
|
557
|
+
expect(representation['things'].size).to eq 4
|
558
|
+
expect(representation['things'].reject { |r| r.kind_of?(subject) }).to be_empty
|
528
559
|
end
|
529
560
|
end
|
530
561
|
end
|
@@ -539,8 +570,8 @@ describe Grape::Entity do
|
|
539
570
|
|
540
571
|
it 'has attribute readers for the object and options' do
|
541
572
|
entity = subject.new('abc', {})
|
542
|
-
entity.object.
|
543
|
-
entity.options.
|
573
|
+
expect(entity.object).to eq 'abc'
|
574
|
+
expect(entity.options).to eq({})
|
544
575
|
end
|
545
576
|
end
|
546
577
|
|
@@ -585,9 +616,9 @@ describe Grape::Entity do
|
|
585
616
|
fresh_class.expose :email, :nonexistent_attribute, :name, safe: true
|
586
617
|
|
587
618
|
res = fresh_class.new(model).serializable_hash
|
588
|
-
res.
|
589
|
-
res.
|
590
|
-
res.
|
619
|
+
expect(res).to have_key :email
|
620
|
+
expect(res).not_to have_key :nonexistent_attribute
|
621
|
+
expect(res).to have_key :name
|
591
622
|
end
|
592
623
|
|
593
624
|
it "does not expose attributes that don't exist on the object, even with criteria" do
|
@@ -596,9 +627,9 @@ describe Grape::Entity do
|
|
596
627
|
fresh_class.expose :nonexistent_attribute2, safe: true, if: lambda { true }
|
597
628
|
|
598
629
|
res = fresh_class.new(model).serializable_hash
|
599
|
-
res.
|
600
|
-
res.
|
601
|
-
res.
|
630
|
+
expect(res).to have_key :email
|
631
|
+
expect(res).not_to have_key :nonexistent_attribute
|
632
|
+
expect(res).not_to have_key :nonexistent_attribute2
|
602
633
|
end
|
603
634
|
end
|
604
635
|
|
@@ -613,7 +644,7 @@ describe Grape::Entity do
|
|
613
644
|
'well, I do exist after all'
|
614
645
|
end
|
615
646
|
res = fresh_class.new(model).serializable_hash
|
616
|
-
res.
|
647
|
+
expect(res).to have_key :nonexistent_attribute
|
617
648
|
end
|
618
649
|
|
619
650
|
it 'does not expose attributes that are generated by a block but have not passed criteria' do
|
@@ -621,7 +652,7 @@ describe Grape::Entity do
|
|
621
652
|
'I exist, but it is not yet my time to shine'
|
622
653
|
}, if: lambda { |_model, _opts| false }
|
623
654
|
res = fresh_class.new(model).serializable_hash
|
624
|
-
res.
|
655
|
+
expect(res).not_to have_key :nonexistent_attribute
|
625
656
|
end
|
626
657
|
end
|
627
658
|
|
@@ -635,7 +666,7 @@ describe Grape::Entity do
|
|
635
666
|
'well, I do exist after all'
|
636
667
|
end
|
637
668
|
res = fresh_class.new(model).serializable_hash
|
638
|
-
res.
|
669
|
+
expect(res).to have_key :nonexistent_attribute
|
639
670
|
end
|
640
671
|
|
641
672
|
it 'does not expose attributes that are generated by a block but have not passed criteria' do
|
@@ -643,7 +674,7 @@ describe Grape::Entity do
|
|
643
674
|
'I exist, but it is not yet my time to shine'
|
644
675
|
}, if: lambda { |_, _| false }
|
645
676
|
res = fresh_class.new(model).serializable_hash
|
646
|
-
res.
|
677
|
+
expect(res).not_to have_key :nonexistent_attribute
|
647
678
|
end
|
648
679
|
|
649
680
|
context '#serializable_hash' do
|
@@ -688,19 +719,19 @@ describe Grape::Entity do
|
|
688
719
|
it 'serializes embedded objects which respond to #serializable_hash' do
|
689
720
|
fresh_class.expose :name, :embedded
|
690
721
|
presenter = fresh_class.new(EntitySpec::EmbeddedExampleWithOne.new)
|
691
|
-
presenter.serializable_hash.
|
722
|
+
expect(presenter.serializable_hash).to eq(name: 'abc', embedded: { abc: 'def' })
|
692
723
|
end
|
693
724
|
|
694
725
|
it 'serializes embedded arrays of objects which respond to #serializable_hash' do
|
695
726
|
fresh_class.expose :name, :embedded
|
696
727
|
presenter = fresh_class.new(EntitySpec::EmbeddedExampleWithMany.new)
|
697
|
-
presenter.serializable_hash.
|
728
|
+
expect(presenter.serializable_hash).to eq(name: 'abc', embedded: [{ abc: 'def' }, { abc: 'def' }])
|
698
729
|
end
|
699
730
|
|
700
731
|
it 'serializes embedded hashes of objects which respond to #serializable_hash' do
|
701
732
|
fresh_class.expose :name, :embedded
|
702
733
|
presenter = fresh_class.new(EntitySpec::EmbeddedExampleWithHash.new)
|
703
|
-
presenter.serializable_hash.
|
734
|
+
expect(presenter.serializable_hash).to eq(name: 'abc', embedded: { a: nil, b: { abc: 'def' } })
|
704
735
|
end
|
705
736
|
end
|
706
737
|
end
|
@@ -725,14 +756,14 @@ describe Grape::Entity do
|
|
725
756
|
end
|
726
757
|
|
727
758
|
it 'passes through bare expose attributes' do
|
728
|
-
subject.send(:value_for, :name).
|
759
|
+
expect(subject.send(:value_for, :name)).to eq attributes[:name]
|
729
760
|
end
|
730
761
|
|
731
762
|
it 'instantiates a representation if that is called for' do
|
732
763
|
rep = subject.send(:value_for, :friends)
|
733
|
-
rep.reject { |r| r.is_a?(fresh_class) }.
|
734
|
-
rep.first.serializable_hash[:name].
|
735
|
-
rep.last.serializable_hash[:name].
|
764
|
+
expect(rep.reject { |r| r.is_a?(fresh_class) }).to be_empty
|
765
|
+
expect(rep.first.serializable_hash[:name]).to eq 'Friend 1'
|
766
|
+
expect(rep.last.serializable_hash[:name]).to eq 'Friend 2'
|
736
767
|
end
|
737
768
|
|
738
769
|
context 'child representations' do
|
@@ -749,10 +780,10 @@ describe Grape::Entity do
|
|
749
780
|
end
|
750
781
|
|
751
782
|
rep = subject.send(:value_for, :friends)
|
752
|
-
rep.
|
753
|
-
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.
|
754
|
-
rep.first.serializable_hash[:name].
|
755
|
-
rep.last.serializable_hash[:name].
|
783
|
+
expect(rep).to be_kind_of Array
|
784
|
+
expect(rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }).to be_empty
|
785
|
+
expect(rep.first.serializable_hash[:name]).to eq 'Friend 1'
|
786
|
+
expect(rep.last.serializable_hash[:name]).to eq 'Friend 2'
|
756
787
|
end
|
757
788
|
|
758
789
|
it 'passes through the proc which returns an array of objects with custom options(:using)' do
|
@@ -770,10 +801,10 @@ describe Grape::Entity do
|
|
770
801
|
end
|
771
802
|
|
772
803
|
rep = subject.send(:value_for, :custom_friends)
|
773
|
-
rep.
|
774
|
-
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.
|
775
|
-
rep.first.serializable_hash.
|
776
|
-
rep.last.serializable_hash.
|
804
|
+
expect(rep).to be_kind_of Array
|
805
|
+
expect(rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }).to be_empty
|
806
|
+
expect(rep.first.serializable_hash).to eq(name: 'Friend 1', email: 'friend1@example.com')
|
807
|
+
expect(rep.last.serializable_hash).to eq(name: 'Friend 2', email: 'friend2@example.com')
|
777
808
|
end
|
778
809
|
|
779
810
|
it 'passes through the proc which returns single object with custom options(:using)' do
|
@@ -791,8 +822,8 @@ describe Grape::Entity do
|
|
791
822
|
end
|
792
823
|
|
793
824
|
rep = subject.send(:value_for, :first_friend)
|
794
|
-
rep.
|
795
|
-
rep.serializable_hash.
|
825
|
+
expect(rep).to be_kind_of EntitySpec::FriendEntity
|
826
|
+
expect(rep.serializable_hash).to eq(name: 'Friend 1', email: 'friend1@example.com')
|
796
827
|
end
|
797
828
|
|
798
829
|
it 'passes through the proc which returns empty with custom options(:using)' do
|
@@ -809,8 +840,8 @@ describe Grape::Entity do
|
|
809
840
|
end
|
810
841
|
|
811
842
|
rep = subject.send(:value_for, :first_friend)
|
812
|
-
rep.
|
813
|
-
rep.serializable_hash.
|
843
|
+
expect(rep).to be_kind_of EntitySpec::FriendEntity
|
844
|
+
expect(rep.serializable_hash).to be_nil
|
814
845
|
end
|
815
846
|
|
816
847
|
it 'passes through custom options' do
|
@@ -827,16 +858,16 @@ describe Grape::Entity do
|
|
827
858
|
end
|
828
859
|
|
829
860
|
rep = subject.send(:value_for, :friends)
|
830
|
-
rep.
|
831
|
-
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.
|
832
|
-
rep.first.serializable_hash[:email].
|
833
|
-
rep.last.serializable_hash[:email].
|
861
|
+
expect(rep).to be_kind_of Array
|
862
|
+
expect(rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }).to be_empty
|
863
|
+
expect(rep.first.serializable_hash[:email]).to be_nil
|
864
|
+
expect(rep.last.serializable_hash[:email]).to be_nil
|
834
865
|
|
835
866
|
rep = subject.send(:value_for, :friends, user_type: :admin)
|
836
|
-
rep.
|
837
|
-
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.
|
838
|
-
rep.first.serializable_hash[:email].
|
839
|
-
rep.last.serializable_hash[:email].
|
867
|
+
expect(rep).to be_kind_of Array
|
868
|
+
expect(rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }).to be_empty
|
869
|
+
expect(rep.first.serializable_hash[:email]).to eq 'friend1@example.com'
|
870
|
+
expect(rep.last.serializable_hash[:email]).to eq 'friend2@example.com'
|
840
871
|
end
|
841
872
|
|
842
873
|
it 'ignores the :collection parameter in the source options' do
|
@@ -853,23 +884,23 @@ describe Grape::Entity do
|
|
853
884
|
end
|
854
885
|
|
855
886
|
rep = subject.send(:value_for, :friends, collection: false)
|
856
|
-
rep.
|
857
|
-
rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }.
|
858
|
-
rep.first.serializable_hash[:email].
|
859
|
-
rep.last.serializable_hash[:email].
|
887
|
+
expect(rep).to be_kind_of Array
|
888
|
+
expect(rep.reject { |r| r.is_a?(EntitySpec::FriendEntity) }).to be_empty
|
889
|
+
expect(rep.first.serializable_hash[:email]).to eq 'friend1@example.com'
|
890
|
+
expect(rep.last.serializable_hash[:email]).to eq 'friend2@example.com'
|
860
891
|
end
|
861
892
|
end
|
862
893
|
|
863
894
|
it 'calls through to the proc if there is one' do
|
864
|
-
subject.send(:value_for, :computed, awesome: 123).
|
895
|
+
expect(subject.send(:value_for, :computed, awesome: 123)).to eq 123
|
865
896
|
end
|
866
897
|
|
867
898
|
it 'returns a formatted value if format_with is passed' do
|
868
|
-
subject.send(:value_for, :birthday).
|
899
|
+
expect(subject.send(:value_for, :birthday)).to eq '02/27/2012'
|
869
900
|
end
|
870
901
|
|
871
902
|
it 'returns a formatted value if format_with is passed a lambda' do
|
872
|
-
subject.send(:value_for, :fantasies).
|
903
|
+
expect(subject.send(:value_for, :fantasies)).to eq ['Nessy', 'Double Rainbows', 'Unicorns']
|
873
904
|
end
|
874
905
|
|
875
906
|
it 'tries instance methods on the entity first' do
|
@@ -889,8 +920,8 @@ describe Grape::Entity do
|
|
889
920
|
|
890
921
|
friend = double('Friend', name: 'joe', email: 'joe@example.com')
|
891
922
|
rep = EntitySpec::DelegatingEntity.new(friend)
|
892
|
-
rep.send(:value_for, :name).
|
893
|
-
rep.send(:value_for, :email).
|
923
|
+
expect(rep.send(:value_for, :name)).to eq 'cooler name'
|
924
|
+
expect(rep.send(:value_for, :email)).to eq 'joe@example.com'
|
894
925
|
end
|
895
926
|
|
896
927
|
context 'using' do
|
@@ -907,9 +938,9 @@ describe Grape::Entity do
|
|
907
938
|
end
|
908
939
|
|
909
940
|
rep = subject.send(:value_for, :friends)
|
910
|
-
rep.
|
911
|
-
rep.size.
|
912
|
-
rep.all? { |r| r.is_a?(EntitySpec::UserEntity) }.
|
941
|
+
expect(rep).to be_kind_of Array
|
942
|
+
expect(rep.size).to eq 2
|
943
|
+
expect(rep.all? { |r| r.is_a?(EntitySpec::UserEntity) }).to be true
|
913
944
|
end
|
914
945
|
|
915
946
|
it 'class' do
|
@@ -918,9 +949,9 @@ describe Grape::Entity do
|
|
918
949
|
end
|
919
950
|
|
920
951
|
rep = subject.send(:value_for, :friends)
|
921
|
-
rep.
|
922
|
-
rep.size.
|
923
|
-
rep.all? { |r| r.is_a?(EntitySpec::UserEntity) }.
|
952
|
+
expect(rep).to be_kind_of Array
|
953
|
+
expect(rep.size).to eq 2
|
954
|
+
expect(rep.all? { |r| r.is_a?(EntitySpec::UserEntity) }).to be true
|
924
955
|
end
|
925
956
|
end
|
926
957
|
end
|
@@ -929,7 +960,7 @@ describe Grape::Entity do
|
|
929
960
|
it 'returns an empty hash is no documentation is provided' do
|
930
961
|
fresh_class.expose :name
|
931
962
|
|
932
|
-
subject.documentation.
|
963
|
+
expect(subject.documentation).to eq({})
|
933
964
|
end
|
934
965
|
|
935
966
|
it 'returns each defined documentation hash' do
|
@@ -938,7 +969,7 @@ describe Grape::Entity do
|
|
938
969
|
fresh_class.expose :email, documentation: doc
|
939
970
|
fresh_class.expose :birthday
|
940
971
|
|
941
|
-
subject.documentation.
|
972
|
+
expect(subject.documentation).to eq(name: doc, email: doc)
|
942
973
|
end
|
943
974
|
|
944
975
|
it 'returns each defined documentation hash with :as param considering' do
|
@@ -947,24 +978,24 @@ describe Grape::Entity do
|
|
947
978
|
fresh_class.expose :email, documentation: doc
|
948
979
|
fresh_class.expose :birthday
|
949
980
|
|
950
|
-
subject.documentation.
|
981
|
+
expect(subject.documentation).to eq(label: doc, email: doc)
|
951
982
|
end
|
952
983
|
end
|
953
984
|
|
954
985
|
describe '#key_for' do
|
955
986
|
it 'returns the attribute if no :as is set' do
|
956
987
|
fresh_class.expose :name
|
957
|
-
subject.class.send(:key_for, :name).
|
988
|
+
expect(subject.class.send(:key_for, :name)).to eq :name
|
958
989
|
end
|
959
990
|
|
960
991
|
it 'returns a symbolized version of the attribute' do
|
961
992
|
fresh_class.expose :name
|
962
|
-
subject.class.send(:key_for, 'name').
|
993
|
+
expect(subject.class.send(:key_for, 'name')).to eq :name
|
963
994
|
end
|
964
995
|
|
965
996
|
it 'returns the :as alias if one exists' do
|
966
997
|
fresh_class.expose :name, as: :nombre
|
967
|
-
subject.class.send(:key_for, 'name').
|
998
|
+
expect(subject.class.send(:key_for, 'name')).to eq :nombre
|
968
999
|
end
|
969
1000
|
end
|
970
1001
|
|
@@ -972,54 +1003,54 @@ describe Grape::Entity do
|
|
972
1003
|
it 'only passes through hash :if exposure if all attributes match' do
|
973
1004
|
exposure_options = { if: { condition1: true, condition2: true } }
|
974
1005
|
|
975
|
-
subject.send(:conditions_met?, exposure_options, {}).
|
976
|
-
subject.send(:conditions_met?, exposure_options, condition1: true).
|
977
|
-
subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true).
|
978
|
-
subject.send(:conditions_met?, exposure_options, condition1: false, condition2: true).
|
979
|
-
subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true, other: true).
|
1006
|
+
expect(subject.send(:conditions_met?, exposure_options, {})).to be false
|
1007
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: true)).to be false
|
1008
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true)).to be true
|
1009
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: false, condition2: true)).to be false
|
1010
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true, other: true)).to be true
|
980
1011
|
end
|
981
1012
|
|
982
1013
|
it 'looks for presence/truthiness if a symbol is passed' do
|
983
1014
|
exposure_options = { if: :condition1 }
|
984
1015
|
|
985
|
-
subject.send(:conditions_met?, exposure_options, {}).
|
986
|
-
subject.send(:conditions_met?, exposure_options, condition1: true).
|
987
|
-
subject.send(:conditions_met?, exposure_options, condition1: false).
|
988
|
-
subject.send(:conditions_met?, exposure_options, condition1: nil).
|
1016
|
+
expect(subject.send(:conditions_met?, exposure_options, {})).to be false
|
1017
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: true)).to be true
|
1018
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: false)).to be false
|
1019
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: nil)).to be false
|
989
1020
|
end
|
990
1021
|
|
991
1022
|
it 'looks for absence/falsiness if a symbol is passed' do
|
992
1023
|
exposure_options = { unless: :condition1 }
|
993
1024
|
|
994
|
-
subject.send(:conditions_met?, exposure_options, {}).
|
995
|
-
subject.send(:conditions_met?, exposure_options, condition1: true).
|
996
|
-
subject.send(:conditions_met?, exposure_options, condition1: false).
|
997
|
-
subject.send(:conditions_met?, exposure_options, condition1: nil).
|
1025
|
+
expect(subject.send(:conditions_met?, exposure_options, {})).to be true
|
1026
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: true)).to be false
|
1027
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: false)).to be true
|
1028
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: nil)).to be true
|
998
1029
|
end
|
999
1030
|
|
1000
1031
|
it 'only passes through proc :if exposure if it returns truthy value' do
|
1001
1032
|
exposure_options = { if: lambda { |_, opts| opts[:true] } }
|
1002
1033
|
|
1003
|
-
subject.send(:conditions_met?, exposure_options, true: false).
|
1004
|
-
subject.send(:conditions_met?, exposure_options, true: true).
|
1034
|
+
expect(subject.send(:conditions_met?, exposure_options, true: false)).to be false
|
1035
|
+
expect(subject.send(:conditions_met?, exposure_options, true: true)).to be true
|
1005
1036
|
end
|
1006
1037
|
|
1007
1038
|
it 'only passes through hash :unless exposure if any attributes do not match' do
|
1008
1039
|
exposure_options = { unless: { condition1: true, condition2: true } }
|
1009
1040
|
|
1010
|
-
subject.send(:conditions_met?, exposure_options, {}).
|
1011
|
-
subject.send(:conditions_met?, exposure_options, condition1: true).
|
1012
|
-
subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true).
|
1013
|
-
subject.send(:conditions_met?, exposure_options, condition1: false, condition2: true).
|
1014
|
-
subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true, other: true).
|
1015
|
-
subject.send(:conditions_met?, exposure_options, condition1: false, condition2: false).
|
1041
|
+
expect(subject.send(:conditions_met?, exposure_options, {})).to be true
|
1042
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: true)).to be false
|
1043
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true)).to be false
|
1044
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: false, condition2: true)).to be false
|
1045
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: true, condition2: true, other: true)).to be false
|
1046
|
+
expect(subject.send(:conditions_met?, exposure_options, condition1: false, condition2: false)).to be true
|
1016
1047
|
end
|
1017
1048
|
|
1018
1049
|
it 'only passes through proc :unless exposure if it returns falsy value' do
|
1019
1050
|
exposure_options = { unless: lambda { |_, options| options[:true] == true } }
|
1020
1051
|
|
1021
|
-
subject.send(:conditions_met?, exposure_options, true: false).
|
1022
|
-
subject.send(:conditions_met?, exposure_options, true: true).
|
1052
|
+
expect(subject.send(:conditions_met?, exposure_options, true: false)).to be true
|
1053
|
+
expect(subject.send(:conditions_met?, exposure_options, true: true)).to be false
|
1023
1054
|
end
|
1024
1055
|
end
|
1025
1056
|
|
@@ -1027,9 +1058,9 @@ describe Grape::Entity do
|
|
1027
1058
|
subject { Class.new }
|
1028
1059
|
|
1029
1060
|
it 'creates an Entity class when called' do
|
1030
|
-
subject.
|
1061
|
+
expect(subject).not_to be_const_defined :Entity
|
1031
1062
|
subject.send(:include, Grape::Entity::DSL)
|
1032
|
-
subject.
|
1063
|
+
expect(subject).to be_const_defined :Entity
|
1033
1064
|
end
|
1034
1065
|
|
1035
1066
|
context 'pre-mixed' do
|
@@ -1040,19 +1071,19 @@ describe Grape::Entity do
|
|
1040
1071
|
expose :name
|
1041
1072
|
end
|
1042
1073
|
|
1043
|
-
subject.entity_class.exposures.
|
1074
|
+
expect(subject.entity_class.exposures).not_to be_empty
|
1044
1075
|
end
|
1045
1076
|
|
1046
1077
|
it 'is able to expose straight from the class' do
|
1047
1078
|
subject.entity :name, :email
|
1048
|
-
subject.entity_class.exposures.size.
|
1079
|
+
expect(subject.entity_class.exposures.size).to eq 2
|
1049
1080
|
end
|
1050
1081
|
|
1051
1082
|
it 'is able to mix field and advanced exposures' do
|
1052
1083
|
subject.entity :name, :email do
|
1053
1084
|
expose :third
|
1054
1085
|
end
|
1055
|
-
subject.entity_class.exposures.size.
|
1086
|
+
expect(subject.entity_class.exposures.size).to eq 3
|
1056
1087
|
end
|
1057
1088
|
|
1058
1089
|
context 'instance' do
|
@@ -1060,15 +1091,15 @@ describe Grape::Entity do
|
|
1060
1091
|
|
1061
1092
|
describe '#entity' do
|
1062
1093
|
it 'is an instance of the entity class' do
|
1063
|
-
instance.entity.
|
1094
|
+
expect(instance.entity).to be_kind_of(subject.entity_class)
|
1064
1095
|
end
|
1065
1096
|
|
1066
1097
|
it 'has an object of itself' do
|
1067
|
-
instance.entity.object.
|
1098
|
+
expect(instance.entity.object).to eq instance
|
1068
1099
|
end
|
1069
1100
|
|
1070
1101
|
it 'instantiates with options if provided' do
|
1071
|
-
instance.entity(awesome: true).options.
|
1102
|
+
expect(instance.entity(awesome: true).options).to eq(awesome: true)
|
1072
1103
|
end
|
1073
1104
|
end
|
1074
1105
|
end
|