rom-mapper 0.5.1 → 1.0.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.
@@ -1,506 +0,0 @@
1
- require 'spec_helper'
2
- require 'virtus'
3
-
4
- RSpec.describe ROM::Processor::Transproc do
5
- subject(:transproc) { ROM::Processor::Transproc.build(binding, header) }
6
-
7
- let(:binding) { nil }
8
- let(:header) { ROM::Header.coerce(attributes, options) }
9
- let(:options) { {} }
10
-
11
- context 'no mapping' do
12
- let(:attributes) { [[:name]] }
13
- let(:relation) { [{ name: 'Jane' }, { name: 'Joe' }] }
14
-
15
- it 'returns tuples' do
16
- expect(transproc[relation]).to eql(relation)
17
- end
18
- end
19
-
20
- context 'coercing values' do
21
- let(:attributes) { [[:name, type: :string], [:age, type: :integer]] }
22
- let(:relation) { [{ name: :Jane, age: '1' }, { name: :Joe, age: '2' }] }
23
-
24
- it 'returns tuples' do
25
- expect(transproc[relation]).to eql([
26
- { name: 'Jane', age: 1 }, { name: 'Joe', age: 2 }
27
- ])
28
- end
29
- end
30
-
31
- context 'mapping to object' do
32
- let(:options) { { model: model } }
33
-
34
- let(:model) do
35
- Class.new do
36
- include Virtus.value_object
37
- values { attribute :name }
38
- end
39
- end
40
-
41
- let(:attributes) { [[:name]] }
42
- let(:relation) { [{ name: 'Jane' }, { name: 'Joe' }] }
43
-
44
- it 'returns tuples' do
45
- expect(transproc[relation]).to eql([
46
- model.new(name: 'Jane'), model.new(name: 'Joe')
47
- ])
48
- end
49
- end
50
-
51
- context 'renaming keys' do
52
- let(:attributes) do
53
- [[:name, from: 'name']]
54
- end
55
-
56
- let(:options) do
57
- { reject_keys: true }
58
- end
59
-
60
- let(:relation) do
61
- [
62
- { 'name' => 'Jane', 'age' => 21 }, { 'name' => 'Joe', age: 22 }
63
- ]
64
- end
65
-
66
- it 'returns tuples with rejected keys' do
67
- expect(transproc[relation]).to eql([{ name: 'Jane' }, { name: 'Joe' }])
68
- end
69
- end
70
-
71
- context 'copying keys' do
72
- let(:options) do
73
- { copy_keys: true }
74
- end
75
-
76
- let(:attributes) do
77
- [['b', from: 'a'], ['c', from: 'b']]
78
- end
79
-
80
- let(:relation) do
81
- [{ 'a' => 'copy' }]
82
- end
83
-
84
- it 'copies without removing the original' do
85
- expect(transproc[relation]).to eql([{ 'a' => 'copy', 'b' => 'copy', 'c' => 'copy' }])
86
- end
87
- end
88
-
89
- context 'key from existing keys' do
90
- let(:attributes) do
91
- coercer = ->(a, b) { b + a }
92
- [[:c, { from: [:a, :b], coercer: coercer }]]
93
- end
94
-
95
- let(:relation) do
96
- [
97
- { a: 'works', b: 'this' }
98
- ]
99
- end
100
-
101
- let(:expected_result) do
102
- [
103
- { c: 'thisworks' }
104
- ]
105
- end
106
-
107
- let(:copy_keys_expected_result) do
108
- [
109
- { a: 'works', b: 'this', c: 'thisworks'}
110
- ]
111
- end
112
-
113
- it 'returns tuples a new key added based on exsiting keys' do
114
- expect(transproc[relation]).to eql(expected_result)
115
- end
116
-
117
- it 'raises a configuration exception if coercer block does not exist' do
118
- attributes[0][1][:coercer] = nil
119
- expect { transproc[relation] }.to raise_error(ROM::MapperMisconfiguredError)
120
- end
121
-
122
- it 'honors the copy_keys option' do
123
- options.merge!({ copy_keys: true })
124
- expect(transproc[relation]).to eql(copy_keys_expected_result)
125
- end
126
- end
127
-
128
- describe 'rejecting keys' do
129
- let(:options) { { reject_keys: true } }
130
-
131
- let(:attributes) do
132
- [
133
- ['name'],
134
- ['tasks', type: :array, group: true, header: [['title']]]
135
- ]
136
- end
137
-
138
- let(:relation) do
139
- [
140
- { 'name' => 'Jane', 'age' => 21, 'title' => 'Task One' },
141
- { 'name' => 'Jane', 'age' => 21, 'title' => 'Task Two' },
142
- { 'name' => 'Joe', 'age' => 22, 'title' => 'Task One' }
143
- ]
144
- end
145
-
146
- it 'returns tuples with unknown keys rejected' do
147
- expect(transproc[relation]).to eql([
148
- { 'name' => 'Jane',
149
- 'tasks' => [{ 'title' => 'Task One' }, { 'title' => 'Task Two' }] },
150
- { 'name' => 'Joe',
151
- 'tasks' => [{ 'title' => 'Task One' }] }
152
- ])
153
- end
154
- end
155
-
156
- context 'mapping nested hash' do
157
- let(:relation) do
158
- [
159
- { 'name' => 'Jane', 'task' => { 'title' => 'Task One' } },
160
- { 'name' => 'Joe', 'task' => { 'title' => 'Task Two' } }
161
- ]
162
- end
163
-
164
- context 'when no mapping is needed' do
165
- let(:attributes) { [['name'], ['task', type: :hash, header: [[:title]]]] }
166
-
167
- it 'returns tuples' do
168
- expect(transproc[relation]).to eql(relation)
169
- end
170
- end
171
-
172
- context 'with deeply nested hashes' do
173
- context 'when no renaming is required' do
174
- let(:relation) do
175
- [
176
- { 'user' => { 'name' => 'Jane', 'task' => { 'title' => 'Task One' } } },
177
- { 'user' => { 'name' => 'Joe', 'task' => { 'title' => 'Task Two' } } }
178
- ]
179
- end
180
-
181
- let(:attributes) do
182
- [[
183
- 'user', type: :hash, header: [
184
- ['name'],
185
- ['task', type: :hash, header: [['title']]]
186
- ]
187
- ]]
188
- end
189
-
190
- it 'returns tuples' do
191
- expect(transproc[relation]).to eql(relation)
192
- end
193
- end
194
-
195
- context 'when renaming is required' do
196
- let(:relation) do
197
- [
198
- { user: { name: 'Jane', task: { title: 'Task One' } } },
199
- { user: { name: 'Joe', task: { title: 'Task Two' } } }
200
- ]
201
- end
202
-
203
- let(:attributes) do
204
- [[
205
- 'user', type: :hash, header: [
206
- ['name'],
207
- ['task', type: :hash, header: [['title']]]
208
- ]
209
- ]]
210
- end
211
-
212
- it 'returns tuples' do
213
- expect(transproc[relation]).to eql(relation)
214
- end
215
- end
216
- end
217
-
218
- context 'renaming keys' do
219
- context 'when only hash needs renaming' do
220
- let(:attributes) do
221
- [
222
- ['name'],
223
- [:task, from: 'task', type: :hash, header: [[:title, from: 'title']]]
224
- ]
225
- end
226
-
227
- it 'returns tuples with key renamed in the nested hash' do
228
- expect(transproc[relation]).to eql([
229
- { 'name' => 'Jane', :task => { title: 'Task One' } },
230
- { 'name' => 'Joe', :task => { title: 'Task Two' } }
231
- ])
232
- end
233
- end
234
-
235
- context 'when all attributes need renaming' do
236
- let(:attributes) do
237
- [
238
- [:name, from: 'name'],
239
- [:task, from: 'task', type: :hash, header: [[:title, from: 'title']]]
240
- ]
241
- end
242
-
243
- it 'returns tuples with key renamed in the nested hash' do
244
- expect(transproc[relation]).to eql([
245
- { name: 'Jane', task: { title: 'Task One' } },
246
- { name: 'Joe', task: { title: 'Task Two' } }
247
- ])
248
- end
249
- end
250
- end
251
- end
252
-
253
- context 'wrapping tuples' do
254
- let(:relation) do
255
- [
256
- { 'name' => 'Jane', 'title' => 'Task One' },
257
- { 'name' => 'Joe', 'title' => 'Task Two' }
258
- ]
259
- end
260
-
261
- context 'when no mapping is needed' do
262
- let(:attributes) do
263
- [
264
- ['name'],
265
- ['task', type: :hash, wrap: true, header: [['title']]]
266
- ]
267
- end
268
-
269
- it 'returns wrapped tuples' do
270
- expect(transproc[relation]).to eql([
271
- { 'name' => 'Jane', 'task' => { 'title' => 'Task One' } },
272
- { 'name' => 'Joe', 'task' => { 'title' => 'Task Two' } }
273
- ])
274
- end
275
- end
276
-
277
- context 'with deeply wrapped tuples' do
278
- let(:attributes) do
279
- [
280
- ['user', type: :hash, wrap: true, header: [
281
- ['name'],
282
- ['task', type: :hash, wrap: true, header: [['title']]]
283
- ]]
284
- ]
285
- end
286
-
287
- it 'returns wrapped tuples' do
288
- expect(transproc[relation]).to eql([
289
- { 'user' => { 'name' => 'Jane', 'task' => { 'title' => 'Task One' } } },
290
- { 'user' => { 'name' => 'Joe', 'task' => { 'title' => 'Task Two' } } }
291
- ])
292
- end
293
- end
294
-
295
- context 'renaming keys' do
296
- context 'when only wrapped tuple requires renaming' do
297
- let(:attributes) do
298
- [
299
- ['name'],
300
- ['task', type: :hash, wrap: true, header: [[:title, from: 'title']]]
301
- ]
302
- end
303
-
304
- it 'returns wrapped tuples with renamed keys' do
305
- expect(transproc[relation]).to eql([
306
- { 'name' => 'Jane', 'task' => { title: 'Task One' } },
307
- { 'name' => 'Joe', 'task' => { title: 'Task Two' } }
308
- ])
309
- end
310
- end
311
-
312
- context 'when all attributes require renaming' do
313
- let(:attributes) do
314
- [
315
- [:name, from: 'name'],
316
- [:task, type: :hash, wrap: true, header: [[:title, from: 'title']]]
317
- ]
318
- end
319
-
320
- it 'returns wrapped tuples with all keys renamed' do
321
- expect(transproc[relation]).to eql([
322
- { name: 'Jane', task: { title: 'Task One' } },
323
- { name: 'Joe', task: { title: 'Task Two' } }
324
- ])
325
- end
326
- end
327
- end
328
- end
329
-
330
- context 'unwrapping tuples' do
331
- let(:relation) do
332
- [
333
- { 'user' => { 'name' => 'Leo', 'task' => { 'title' => 'Task 1' } } },
334
- { 'user' => { 'name' => 'Joe', 'task' => { 'title' => 'Task 2' } } }
335
- ]
336
- end
337
-
338
- context 'when no mapping is needed' do
339
- let(:attributes) do
340
- [
341
- ['user', type: :hash, unwrap: true, header: [['name'], ['task']]]
342
- ]
343
- end
344
-
345
- it 'returns unwrapped tuples' do
346
- expect(transproc[relation]).to eql([
347
- { 'name' => 'Leo', 'task' => { 'title' => 'Task 1' } },
348
- { 'name' => 'Joe', 'task' => { 'title' => 'Task 2' } }
349
- ])
350
- end
351
- end
352
-
353
- context 'partially' do
354
- context 'without renaming the rest of the wrap' do
355
- let(:attributes) do
356
- [
357
- ['user', type: :hash, unwrap: true, header: [['task']]]
358
- ]
359
- end
360
-
361
- it 'returns unwrapped tuples' do
362
- expect(transproc[relation]).to eql([
363
- { 'user' => { 'name' => 'Leo' }, 'task' => { 'title' => 'Task 1' } },
364
- { 'user' => { 'name' => 'Joe' }, 'task' => { 'title' => 'Task 2' } }
365
- ])
366
- end
367
- end
368
-
369
- context 'with renaming the rest of the wrap' do
370
- let(:attributes) do
371
- [
372
- ['man', from: 'user', type: :hash, unwrap: true, header: [['task']]]
373
- ]
374
- end
375
-
376
- it 'returns unwrapped tuples' do
377
- expect(transproc[relation]).to eql([
378
- { 'man' => { 'name' => 'Leo' }, 'task' => { 'title' => 'Task 1' } },
379
- { 'man' => { 'name' => 'Joe' }, 'task' => { 'title' => 'Task 2' } }
380
- ])
381
- end
382
- end
383
- end
384
-
385
- context 'deeply' do
386
- let(:attributes) do
387
- [
388
- ['user', type: :hash, unwrap: true, header: [
389
- ['name'],
390
- ['title'],
391
- ['task', type: :hash, unwrap: true, header: [['title']]]
392
- ]]
393
- ]
394
- end
395
-
396
- it 'returns unwrapped tuples' do
397
- expect(transproc[relation]).to eql([
398
- { 'name' => 'Leo', 'title' => 'Task 1' },
399
- { 'name' => 'Joe', 'title' => 'Task 2' }
400
- ])
401
- end
402
- end
403
- end
404
-
405
- context 'grouping tuples' do
406
- let(:relation) do
407
- [
408
- { 'name' => 'Jane', 'title' => 'Task One' },
409
- { 'name' => 'Jane', 'title' => 'Task Two' },
410
- { 'name' => 'Joe', 'title' => 'Task One' },
411
- { 'name' => 'Joe', 'title' => nil }
412
- ]
413
- end
414
-
415
- context 'when no mapping is needed' do
416
- let(:attributes) do
417
- [
418
- ['name'],
419
- ['tasks', type: :array, group: true, header: [['title']]]
420
- ]
421
- end
422
-
423
- it 'returns wrapped tuples with all keys renamed' do
424
- expect(transproc[relation]).to eql([
425
- { 'name' => 'Jane',
426
- 'tasks' => [{ 'title' => 'Task One' }, { 'title' => 'Task Two' }] },
427
- { 'name' => 'Joe',
428
- 'tasks' => [{ 'title' => 'Task One' }] }
429
- ])
430
- end
431
- end
432
-
433
- context 'renaming keys' do
434
- context 'when only grouped tuple requires renaming' do
435
- let(:attributes) do
436
- [
437
- ['name'],
438
- ['tasks', type: :array, group: true, header: [[:title, from: 'title']]]
439
- ]
440
- end
441
-
442
- it 'returns grouped tuples with renamed keys' do
443
- expect(transproc[relation]).to eql([
444
- { 'name' => 'Jane',
445
- 'tasks' => [{ title: 'Task One' }, { title: 'Task Two' }] },
446
- { 'name' => 'Joe',
447
- 'tasks' => [{ title: 'Task One' }] }
448
- ])
449
- end
450
- end
451
-
452
- context 'when all attributes require renaming' do
453
- let(:attributes) do
454
- [
455
- [:name, from: 'name'],
456
- [:tasks, type: :array, group: true, header: [[:title, from: 'title']]]
457
- ]
458
- end
459
-
460
- it 'returns grouped tuples with all keys renamed' do
461
- expect(transproc[relation]).to eql([
462
- { name: 'Jane',
463
- tasks: [{ title: 'Task One' }, { title: 'Task Two' }] },
464
- { name: 'Joe',
465
- tasks: [{ title: 'Task One' }] }
466
- ])
467
- end
468
- end
469
- end
470
-
471
- context 'nested grouping' do
472
- let(:relation) do
473
- [
474
- { name: 'Jane', title: 'Task One', tag: 'red' },
475
- { name: 'Jane', title: 'Task One', tag: 'green' },
476
- { name: 'Joe', title: 'Task One', tag: 'blue' }
477
- ]
478
- end
479
-
480
- let(:attributes) do
481
- [
482
- [:name],
483
- [:tasks, type: :array, group: true, header: [
484
- [:title],
485
- [:tags, type: :array, group: true, header: [[:tag]]]
486
- ]]
487
- ]
488
- end
489
-
490
- it 'returns deeply grouped tuples' do
491
- expect(transproc[relation]).to eql([
492
- { name: 'Jane',
493
- tasks: [
494
- { title: 'Task One', tags: [{ tag: 'red' }, { tag: 'green' }] }
495
- ]
496
- },
497
- { name: 'Joe',
498
- tasks: [
499
- { title: 'Task One', tags: [{ tag: 'blue' }] }
500
- ]
501
- }
502
- ])
503
- end
504
- end
505
- end
506
- end