crud-service 0.0.9 → 0.1.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.
@@ -0,0 +1,1363 @@
1
+ require "spec_helper"
2
+
3
+ describe CrudService::Dal do
4
+ before(:each) do
5
+ @mock_mysql = mysql_mock
6
+ @mock_memcache = double('Memcache')
7
+ @mock_log = double('Log')
8
+
9
+ @generic_dal = CrudService::Dal.new(@mock_mysql, @mock_memcache, @mock_log)
10
+ @generic_dal.table_name = "testtable"
11
+ @generic_dal.cache_prefix = "prefix"
12
+ end
13
+
14
+ describe '#initialize' do
15
+ it 'should inject dependencies correctly' do
16
+ expect(@generic_dal.mysql).to eq(@mock_mysql)
17
+ expect(@generic_dal.memcache).to eq(@mock_memcache)
18
+ expect(@generic_dal.log).to eq(@mock_log)
19
+ end
20
+ end
21
+
22
+ describe '#cached_query' do
23
+ it 'should attempt to query the cache before the database' do
24
+
25
+ testdata = [ { "field_one" => "one" } ]
26
+
27
+ mock_result = mysql_result_mock(testdata)
28
+
29
+ query = 'test invalid query'
30
+ query_hash = "prefix-"+Digest::MD5.hexdigest(query+":testtable-1")
31
+
32
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(1)
33
+ expect(@mock_memcache).to receive(:get).ordered.with(query_hash).and_return(nil)
34
+ expect(@mock_mysql).to receive(:query).with(query).and_return(mock_result)
35
+ expect(@mock_memcache).to receive(:set).ordered.with(query_hash, testdata)
36
+
37
+ expect(@generic_dal.cached_query(query,[])).to eq(testdata)
38
+ end
39
+
40
+ it 'should not attempt to query the database on a cache hit' do
41
+ testdata = [ { "field_one" => "one" } ]
42
+ query = 'test invalid query'
43
+ query_hash = "prefix-"+Digest::MD5.hexdigest(query+":testtable-1")
44
+
45
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(1)
46
+ expect(@mock_memcache).to receive(:get).ordered.with(query_hash).and_return(testdata)
47
+ expect(@mock_mysql).not_to receive(:query)
48
+ expect(@mock_memcache).not_to receive(:set).ordered
49
+
50
+ expect(@generic_dal.cached_query(query,[])).to eq(testdata)
51
+ end
52
+
53
+ it 'should handle zero record return' do
54
+ memcache_null(@mock_memcache)
55
+
56
+ query = 'test invalid query'
57
+
58
+ expect(@mock_mysql).to receive(:query).with(query).and_return(mysql_result_mock([]))
59
+
60
+ expect(@generic_dal.cached_query(query,[])).to eq([])
61
+ end
62
+
63
+ it 'should write a new table version to cache when not found' do
64
+ testdata = [ { "field_one" => "one" } ]
65
+
66
+ mock_result = mysql_result_mock(testdata)
67
+
68
+ query = 'test invalid query'
69
+ query_hash = "prefix-"+Digest::MD5.hexdigest(query+":testtable-1")
70
+
71
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(nil)
72
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(nil)
73
+ expect(@mock_memcache).to receive(:set).ordered.with("prefix-testtable-version",1,nil,{:raw=>true})
74
+ expect(@mock_memcache).to receive(:get).ordered.with(query_hash).and_return(nil)
75
+ expect(@mock_mysql).to receive(:query).ordered.with(query).and_return(mock_result)
76
+ expect(@mock_memcache).to receive(:set).ordered.with(query_hash, testdata)
77
+
78
+ expect(@generic_dal.cached_query(query,[])).to eq(testdata)
79
+ end
80
+
81
+ it 'should miss the cache when a table version has changed' do
82
+ testdata = [ { "field_one" => "one" } ]
83
+
84
+ mock_result = mysql_result_mock(testdata)
85
+
86
+ query = 'test invalid query'
87
+ query_hash = "prefix-"+Digest::MD5.hexdigest(query+":testtable-1")
88
+
89
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(1)
90
+ expect(@mock_memcache).to receive(:get).ordered.with(query_hash).and_return(nil)
91
+ expect(@mock_mysql).to receive(:query).with(query).and_return(mock_result)
92
+ expect(@mock_memcache).to receive(:set).ordered.with(query_hash, testdata)
93
+
94
+ expect(@generic_dal.cached_query(query,[])).to eq(testdata)
95
+
96
+ query_hash = "prefix-"+Digest::MD5.hexdigest(query+":testtable-2")
97
+
98
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(2)
99
+ expect(@mock_memcache).to receive(:get).ordered.with(query_hash).and_return(nil)
100
+ expect(@mock_mysql).to receive(:query).with(query).and_return(mock_result)
101
+ expect(@mock_memcache).to receive(:set).ordered.with(query_hash, testdata)
102
+
103
+ expect(@generic_dal.cached_query(query,[])).to eq(testdata)
104
+ end
105
+
106
+ it 'should lok error and return [] if the database query fails' do
107
+ testdata = [ { "field_one" => "one" } ]
108
+
109
+ mock_result = mysql_result_mock(testdata)
110
+
111
+ query = 'test invalid query'
112
+ query_hash = "prefix-"+Digest::MD5.hexdigest(query+":testtable-1")
113
+
114
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(1)
115
+ expect(@mock_memcache).to receive(:get).ordered.with(query_hash).and_return(nil)
116
+ expect(@mock_mysql).to receive(:query).with(query).and_return(mock_result)
117
+ expect(@mock_memcache).to receive(:set).ordered.with(query_hash, testdata)
118
+
119
+ expect(@generic_dal.cached_query(query,[])).to eq(testdata)
120
+
121
+ query_hash = "prefix-"+Digest::MD5.hexdigest(query+":testtable-2")
122
+
123
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(2)
124
+ expect(@mock_memcache).to receive(:get).ordered.with(query_hash).and_return(nil)
125
+ expect(@mock_mysql).to receive(:query) { raise "TestException"}
126
+ expect(@mock_log).to receive(:error).with("TestException")
127
+
128
+ expect(@generic_dal.cached_query(query,[])).to eq([])
129
+ end
130
+
131
+ end
132
+
133
+ describe '#build_where' do
134
+ it 'should return an empty string when called with no query' do
135
+ query = { }
136
+ expect(@generic_dal.build_where(query)).to eq ""
137
+ end
138
+
139
+ it 'should return a valid where clause when called with a single field query string value' do
140
+ query = { "one" => "two" }
141
+ expect(@generic_dal.build_where(query)).to eq "(`one` = 'two')"
142
+ end
143
+
144
+ it 'should return a valid where clause when called with a single field query integer value' do
145
+ query = { "one" => 2 }
146
+ expect(@generic_dal.build_where(query)).to eq "(`one` = 2)"
147
+ end
148
+
149
+ it 'should return a valid where clause when called with a single field query float value' do
150
+ query = { "one" => 2.123 }
151
+ expect(@generic_dal.build_where(query)).to eq "(`one` = 2.123)"
152
+ end
153
+
154
+ it 'should return a valid where clause when called with a multiple field query' do
155
+ query = { "one" => "two", "three" => "four" }
156
+ expect(@generic_dal.build_where(query)).to eq "(`one` = 'two') AND (`three` = 'four')"
157
+ end
158
+
159
+ it 'should return a valid where clause when called with a query with a nil value' do
160
+ query = { "one" => "two", "three" => nil}
161
+ expect(@generic_dal.build_where(query)).to eq "(`one` = 'two') AND (`three` IS NULL)"
162
+ end
163
+
164
+ it 'should escape field names' do
165
+ query = { "on`=1; DROP TABLE countries" => "two" }
166
+ expect(@generic_dal.build_where(query)).to eq "(`on=1; DROP TABLE countries` = 'two')"
167
+ end
168
+
169
+ it 'should escape field values when string based' do
170
+ query = { "one" => "two'; DROP TABLE countries;" }
171
+ expect(@generic_dal.build_where(query)).to eq "(`one` = 'two\\'; DROP TABLE countries;')"
172
+ end
173
+
174
+ it 'should not build include or exclude into queries' do
175
+ query = { "one" => 2, "include" => "subdivisions", "exclude" => "countries", "two"=>3 }
176
+ expect(@generic_dal.build_where(query)).to eq "(`one` = 2) AND (`two` = 3)"
177
+ end
178
+ end
179
+
180
+ describe '#build_where_ns_ns' do
181
+ it 'should return an empty string when called with no query' do
182
+ query = { }
183
+ expect(@generic_dal.build_where_ns(query,'a')).to eq ""
184
+ end
185
+
186
+ it 'should return a valid where clause when called with a single field query string value' do
187
+ query = { "one" => "two" }
188
+ expect(@generic_dal.build_where_ns(query,'b')).to eq "(`b`.`one` = 'two')"
189
+ end
190
+
191
+ it 'should return a valid where clause when called with a single field query integer value' do
192
+ query = { "one" => 2 }
193
+ expect(@generic_dal.build_where_ns(query,'c')).to eq "(`c`.`one` = 2)"
194
+ end
195
+
196
+ it 'should return a valid where clause when called with a single field query float value' do
197
+ query = { "one" => 2.123 }
198
+ expect(@generic_dal.build_where_ns(query,'d')).to eq "(`d`.`one` = 2.123)"
199
+ end
200
+
201
+ it 'should return a valid where clause when called with a multiple field query' do
202
+ query = { "one" => "two", "three" => "four" }
203
+ expect(@generic_dal.build_where_ns(query,'e')).to eq "(`e`.`one` = 'two') AND (`e`.`three` = 'four')"
204
+ end
205
+
206
+ it 'should return a valid where clause when called with a query with a nil value' do
207
+ query = { "one" => "two", "three" => nil}
208
+ expect(@generic_dal.build_where_ns(query,'f')).to eq "(`f`.`one` = 'two') AND (`f`.`three` IS NULL)"
209
+ end
210
+
211
+ it 'should escape field names' do
212
+ query = { "on`=1; DROP TABLE countries" => "two" }
213
+ expect(@generic_dal.build_where_ns(query,'g')).to eq "(`g`.`on=1; DROP TABLE countries` = 'two')"
214
+ end
215
+
216
+ it 'should escape field values when string based' do
217
+ query = { "one" => "two'; DROP TABLE countries;" }
218
+ expect(@generic_dal.build_where_ns(query,'h')).to eq "(`h`.`one` = 'two\\'; DROP TABLE countries;')"
219
+ end
220
+
221
+ it 'should not build include or exclude into queries' do
222
+ query = { "one" => 2, "include" => "subdivisions", "exclude" => "countries", "two"=>3 }
223
+ expect(@generic_dal.build_where_ns(query,'i')).to eq "(`i`.`one` = 2) AND (`i`.`two` = 3)"
224
+ end
225
+ end
226
+
227
+ describe '#build_fields' do
228
+ it 'should return an empty string with no fields' do
229
+ expect(@generic_dal.build_select_fields([],nil)).to eq ""
230
+ end
231
+
232
+ it 'should return fields correctly' do
233
+ expect(@generic_dal.build_select_fields(['one','two'],nil)).to eq "`one`,`two`"
234
+ end
235
+
236
+ it 'should return namespaced fields correctly' do
237
+ expect(@generic_dal.build_select_fields(['one','two'],'a')).to eq "`a`.`one`,`a`.`two`"
238
+ end
239
+ end
240
+
241
+ describe '#build_fields' do
242
+ before(:each) do
243
+ @generic_dal.fields = {
244
+ "test1" => { :type=>:string },
245
+ "test2" => { :type=>:string },
246
+ "testX" => { :type=>:string },
247
+ }
248
+ end
249
+
250
+ it 'should return all fields with nil excludes' do
251
+ expect(@generic_dal.build_fields({})).to eq "`test1`,`test2`,`testX`"
252
+ end
253
+
254
+ it 'should return all fields with empty excludes' do
255
+ expect(@generic_dal.build_fields({"exclude"=>nil})).to eq "`test1`,`test2`,`testX`"
256
+ end
257
+
258
+ it 'should exclude a single field' do
259
+ expect(@generic_dal.build_fields({"exclude"=>'test1'})).to eq "`test2`,`testX`"
260
+ end
261
+
262
+ it 'should exclude multiple fields' do
263
+ expect(@generic_dal.build_fields({"exclude"=>'test1,testX'})).to eq "`test2`"
264
+ end
265
+ end
266
+
267
+ describe '#build_fields_with_ns' do
268
+ before(:each) do
269
+ @generic_dal.fields = {
270
+ "test1" => { :type=>:string },
271
+ "test2" => { :type=>:string },
272
+ "testX" => { :type=>:string },
273
+ }
274
+ end
275
+
276
+ it 'should return all fields with nil excludes' do
277
+ expect(@generic_dal.build_fields_with_ns({},'a')).to eq "`a`.`test1`,`a`.`test2`,`a`.`testX`"
278
+ end
279
+
280
+ it 'should return all fields with empty excludes' do
281
+ expect(@generic_dal.build_fields_with_ns({"exclude"=>nil},'b')).to eq "`b`.`test1`,`b`.`test2`,`b`.`testX`"
282
+ end
283
+
284
+ it 'should exclude a single field' do
285
+ expect(@generic_dal.build_fields_with_ns({"exclude"=>'test1'},'c')).to eq "`c`.`test2`,`c`.`testX`"
286
+ end
287
+
288
+ it 'should exclude multiple fields' do
289
+ expect(@generic_dal.build_fields_with_ns({"exclude"=>'test1,testX'},'d')).to eq "`d`.`test2`"
290
+ end
291
+ end
292
+
293
+ describe '#get_includes' do
294
+ before(:each) do
295
+ @generic_dal.fields = ["test1", "test2", "testX"]
296
+ end
297
+
298
+ it 'should return an empty array with a nil query' do
299
+ expect(@generic_dal.get_includes(nil)).to eq []
300
+ end
301
+
302
+ it 'should return an empty array with no fields or includes' do
303
+ query = { }
304
+ expect(@generic_dal.get_includes(query)).to eq []
305
+ end
306
+
307
+ it 'should return an empty array with fields and no includes' do
308
+ query = { "field2" => "xxas"}
309
+ expect(@generic_dal.get_includes(query)).to eq []
310
+ end
311
+
312
+ it 'should return a single include' do
313
+ query = { "include"=>"test1" }
314
+ expect(@generic_dal.get_includes(query)).to eq ['test1']
315
+ end
316
+
317
+ it 'should return multiple includes' do
318
+ query = { "include"=>"test1,test2"}
319
+ expect(@generic_dal.get_includes(query)).to eq ['test1','test2']
320
+ end
321
+ end
322
+
323
+ describe '#get_excludes' do
324
+ before(:each) do
325
+ @generic_dal.fields = {
326
+ "test1" => { :type=>:string },
327
+ "test2" => { :type=>:string },
328
+ "testX" => { :type=>:string },
329
+ }
330
+ end
331
+
332
+ it 'should return an empty array with a nil query' do
333
+ expect(@generic_dal.get_excludes(nil)).to eq []
334
+ end
335
+
336
+ it 'should return an empty array with no fields or excludes' do
337
+ query = { }
338
+ expect(@generic_dal.get_excludes(query)).to eq []
339
+ end
340
+
341
+ it 'should return an empty array with fields and no excludes' do
342
+ query = { "field2" => "xxas"}
343
+ expect(@generic_dal.get_excludes(query)).to eq []
344
+ end
345
+
346
+ it 'should return a single exclude' do
347
+ query = { "exclude"=>"test1", "field2" => "xxas"}
348
+ expect(@generic_dal.get_excludes(query)).to eq ['test1']
349
+ end
350
+
351
+ it 'should return multiple excludes' do
352
+ query = { "exclude"=>"test1,test2"}
353
+ expect(@generic_dal.get_excludes(query)).to eq ['test1','test2']
354
+ end
355
+ end
356
+
357
+ describe '#build_equal_condition' do
358
+ it 'should return IS NULL for a nil' do
359
+ expect(@generic_dal.build_equal_condition(nil)).to eq 'IS NULL'
360
+ end
361
+
362
+ it 'should return correct response for an integer' do
363
+ expect(@generic_dal.build_equal_condition(1)).to eq '= 1'
364
+ end
365
+
366
+ it 'should return correct response for a float' do
367
+ expect(@generic_dal.build_equal_condition(1.123)).to eq '= 1.123'
368
+ end
369
+
370
+ it 'should return correct response for a string' do
371
+ expect(@generic_dal.build_equal_condition('ABC')).to eq "= 'ABC'"
372
+ end
373
+
374
+ it 'should return correct escaped response for a string' do
375
+ expect(@generic_dal.build_equal_condition("AB'; DROP TABLE test_table --")).to eq "= 'AB\\'; DROP TABLE test_table --'"
376
+ end
377
+ end
378
+
379
+ describe '#valid_query?' do
380
+ before(:each) do
381
+ @generic_dal.fields = {
382
+ "one" => { :type=>:string },
383
+ "two" => { :type=>:string },
384
+ "three" => { :type=>:string },
385
+ }
386
+ @generic_dal.relations = {
387
+ "four" => { :type=>:string },
388
+ "five" => { :type=>:string },
389
+ "six" => { :type=>:string },
390
+ }
391
+ end
392
+
393
+ it 'should return true with valid fields' do
394
+ expect(@generic_dal.valid_query?({"one"=>1})).to be true
395
+ end
396
+
397
+ it 'should return false with invalid fields' do
398
+ expect(@generic_dal.valid_query?({"five"=>1})).to be false
399
+ end
400
+
401
+ it 'should return true with valid relations' do
402
+ expect(@generic_dal.valid_query?({"include"=>'four,five'})).to be true
403
+ end
404
+
405
+ it 'should return false with invalid relations' do
406
+ expect(@generic_dal.valid_query?({"include"=>'ten'})).to be false
407
+ end
408
+
409
+ it 'should return false with nil' do
410
+ expect(@generic_dal.valid_query?(nil)).to be false
411
+ end
412
+
413
+ it 'should return true with no fields' do
414
+ expect(@generic_dal.valid_query?({})).to be true
415
+ end
416
+
417
+ it 'should return true regardless of include' do
418
+ expect(@generic_dal.valid_query?({"one"=>1,"include"=>"two"})).to be true
419
+ end
420
+
421
+ it 'should return true regardless of exclude' do
422
+ expect(@generic_dal.valid_query?({"one"=>1,"exclude"=>"one"})).to be true
423
+ end
424
+
425
+ it 'should return false as cannot exclude a relation' do
426
+ expect(@generic_dal.valid_query?({"one"=>1,"exclude"=>"five"})).to be false
427
+ end
428
+ end
429
+
430
+ describe '#escape_str_field' do
431
+ it 'should escape single quotes' do
432
+ expect(@generic_dal.escape_str_field("ABC'BC")).to eq "ABC\\'BC"
433
+ end
434
+
435
+ it 'should remove backtics' do
436
+ expect(@generic_dal.escape_str_field("ABC`BC")).to eq "ABCBC"
437
+ end
438
+
439
+ it 'should resolve symbols as well as strings' do
440
+ expect(@generic_dal.escape_str_field(:testing)).to eq "testing"
441
+ end
442
+ end
443
+
444
+ describe '#get_all_by_query' do
445
+ it 'should call cached_query with the correct query for one field' do
446
+ memcache_null(@mock_memcache)
447
+ @generic_dal.fields = {
448
+ "one" => { :type=>:string },
449
+ "two" => { :type=>:string },
450
+ }
451
+ @generic_dal.table_name = 'test_table'
452
+
453
+ expect(@mock_mysql).to receive(:query).with("SELECT `one`,`two` FROM `test_table` WHERE (`field` = 'test2')")
454
+
455
+ @generic_dal.get_all_by_query({ :field => 'test2' })
456
+ end
457
+
458
+ it 'should call cached_query with the correct query for multiple fields' do
459
+ memcache_null(@mock_memcache)
460
+ @generic_dal.fields = {
461
+ "one" => { :type=>:string },
462
+ "two" => { :type=>:string },
463
+ }
464
+ @generic_dal.table_name = 'test_table'
465
+
466
+ expect(@mock_mysql).to receive(:query).with("SELECT `one`,`two` FROM `test_table` WHERE (`field` = 'test2') AND (`twofield` = 2) AND (`nullfield` IS NULL)")
467
+
468
+ @generic_dal.get_all_by_query({ :field => 'test2', "twofield" =>2, "nullfield" => nil })
469
+ end
470
+ end
471
+
472
+ describe '#get_last_id' do
473
+ it 'should call mysql last_id' do
474
+ expect(@mock_mysql).to receive(:last_id)
475
+ @generic_dal.get_last_id
476
+ end
477
+ end
478
+
479
+ describe '#get_one' do
480
+ before(:each) do
481
+ memcache_null(@mock_memcache)
482
+
483
+ @generic_dal.fields = {
484
+ "one" => { :type=>:string },
485
+ "two" => { :type=>:string },
486
+ }
487
+
488
+ @generic_dal.table_name = 'test_table'
489
+
490
+ @mock_result = mysql_result_mock([
491
+ { "field_one" => "one" },
492
+ { "field_one" => "two" }
493
+ ])
494
+ end
495
+
496
+ it 'should call cached_query with the correct query for one field and return a single object' do
497
+ expect(@mock_mysql).to receive(:query)
498
+ .with("SELECT `one`,`two` FROM `test_table` WHERE (`field` = 'test2')")
499
+ .and_return(@mock_result)
500
+
501
+ expect(@generic_dal.get_one({ :field => 'test2' })).to eq({ "field_one" => "one" })
502
+ end
503
+
504
+ it 'should call cached_query with the correct query for one field and return a single object' do
505
+ expect(@mock_mysql).to receive(:query)
506
+ .with("SELECT `one`,`two` FROM `test_table` WHERE (`field` = 'test2') AND (`field_two` = 'test3')")
507
+ .and_return(@mock_result)
508
+
509
+ expect(@generic_dal.get_one({ :field => 'test2', :field_two => 'test3' })).to eq({ "field_one" => "one" })
510
+ end
511
+ end
512
+
513
+ describe '#map_to_hash_by_primary_key' do
514
+ before(:each) do
515
+ @generic_dal.primary_key = 'id'
516
+ end
517
+
518
+ it 'should return an empty hash when given an empty array' do
519
+ test = []
520
+
521
+ expect(@generic_dal.map_to_hash_by_primary_key(test)).to eq({})
522
+ end
523
+
524
+ it 'should correctly map an array' do
525
+ test = [
526
+ { "id" => 1, "field_one" => "one" },
527
+ { "id" => 2.5, "field_one" => "two point five" },
528
+ { "id" => "3", "field_one" => "three" },
529
+ { "id" => nil, "field_one" => "four" }
530
+ ]
531
+
532
+ expect(@generic_dal.map_to_hash_by_primary_key(test)).to eq({
533
+ 1 => { "id" => 1, "field_one" => "one" },
534
+ 2.5 => { "id" => 2.5, "field_one" => "two point five" },
535
+ "3" => { "id" => "3", "field_one" => "three" },
536
+ nil => { "id" => nil, "field_one" => "four" }
537
+ })
538
+ end
539
+ end
540
+
541
+ describe '#remove_key_from_hash_of_arrays!' do
542
+
543
+ it 'should remove a key from each hash in each array in each hash value' do
544
+
545
+ test = {
546
+ 'one' => [ ],
547
+ 2 => [ {"x" => 'a', "y" => 'b', 'z' => 'c' } ],
548
+ nil => [ {"x" => 'd', "y" => 'e', 'z' => 'f' }, {"x" => 'g', "y" => 'h', 'z' => 'i' } ],
549
+ }
550
+
551
+ @generic_dal.remove_key_from_hash_of_arrays!(test,'z')
552
+
553
+ expect(test).to eq({
554
+ 'one' => [ ],
555
+ 2 => [ {"x" => 'a', "y" => 'b'} ],
556
+ nil => [ {"x" => 'd', "y" => 'e' }, {"x" => 'g', "y" => 'h' } ],
557
+ })
558
+
559
+ end
560
+ end
561
+
562
+ describe '#map_to_hash_of_arrays_by_key' do
563
+ it 'should return an empty hash when given an empty array' do
564
+ test = []
565
+
566
+ expect(@generic_dal.map_to_hash_of_arrays_by_key(test,'field_one')).to eq({})
567
+ end
568
+
569
+ it 'should correctly map an array' do
570
+ test = [
571
+ { "id" => 1, "field_one" => 1 },
572
+ { "id" => 2.5, "field_one" => "two point five" },
573
+ { "id" => "3", "field_one" => "three" },
574
+ { "id" => nil, "field_one" => 4.5 },
575
+ { "id" => nil, "field_one" => 1 },
576
+ { "id" => 90, "field_one" => "two point five" },
577
+ { "id" => nil, "field_one" => "four" },
578
+ { "id" => "16", "field_one" => "three" },
579
+ { "id" => 2.1, "field_one" => 4.5 },
580
+ { "id" => 328, "field_one" => "one" },
581
+ { "id" => nil, "field_one" => nil },
582
+ { "id" => 123, "field_one" => nil },
583
+ ]
584
+
585
+ expect(@generic_dal.map_to_hash_of_arrays_by_key(test,'field_one')).to eq({
586
+ nil => [
587
+ { "id" => nil, "field_one" => nil },
588
+ { "id" => 123, "field_one" => nil },
589
+ ],
590
+ 1 => [
591
+ { "id" => 1, "field_one" => 1 },
592
+ { "id" => nil, "field_one" => 1 },
593
+ ],
594
+ "two point five" => [
595
+ { "id" => 2.5, "field_one" => "two point five" },
596
+ { "id" => 90, "field_one" => "two point five" },
597
+ ],
598
+ "three" => [
599
+ { "id" => "3", "field_one" => "three" },
600
+ { "id" => "16", "field_one" => "three" },
601
+ ],
602
+ "four" => [
603
+ { "id" => nil, "field_one" => "four" },
604
+ ],
605
+ 4.5 => [
606
+ { "id" => nil, "field_one" => 4.5 },
607
+ { "id" => 2.1, "field_one" => 4.5 },
608
+ ],
609
+ "one" => [
610
+ { "id" => 328, "field_one" => "one" },
611
+ ]
612
+ })
613
+ end
614
+ end
615
+
616
+ describe '#add_field_from_map!' do
617
+ it 'should map correctly' do
618
+ records = [
619
+ {"id"=>1, "fk_code"=>"EU", "name"=>"Test1" },
620
+ {"id"=>2, "fk_code"=>"EU", "name"=>"Test2" },
621
+ {"id"=>3, "fk_code"=>"AU", "name"=>"Test3" },
622
+ {"id"=>4, "fk_code"=>"GB", "name"=>"Test4" },
623
+ {"id"=>5, "fk_code"=>"US", "name"=>"Test5" },
624
+ {"id"=>6, "fk_code"=>nil, "name"=>"Test5" },
625
+ ]
626
+
627
+ map = {
628
+ 'EU' => 1,
629
+ 'AU' => { "name"=>"one" },
630
+ 'US' => nil,
631
+ 'GB' => "test!"
632
+ }
633
+
634
+ @generic_dal.add_field_from_map!(records, map, 'fk_field', 'fk_code')
635
+
636
+ expect(records).to eq [
637
+ {"id"=>1, "fk_code"=>"EU", "name"=>"Test1", "fk_field"=>1 },
638
+ {"id"=>2, "fk_code"=>"EU", "name"=>"Test2", "fk_field"=>1 },
639
+ {"id"=>3, "fk_code"=>"AU", "name"=>"Test3", "fk_field"=>{ "name"=>"one" } },
640
+ {"id"=>4, "fk_code"=>"GB", "name"=>"Test4", "fk_field"=>"test!" },
641
+ {"id"=>5, "fk_code"=>"US", "name"=>"Test5", "fk_field"=>nil },
642
+ {"id"=>6, "fk_code"=>nil, "name"=>"Test5" },
643
+ ]
644
+
645
+ end
646
+ end
647
+
648
+ describe '#get_relation_query_sql' do
649
+ it 'should return the correct sql for a has_one relation with no query' do
650
+
651
+ @generic_dal.table_name = "currencies"
652
+
653
+ rel = {
654
+ :type => :has_one,
655
+ :table => 'countries',
656
+ :table_key => 'default_currency_code',
657
+ :this_key => 'code',
658
+ :table_fields => 'code_alpha_2,name',
659
+ }
660
+
661
+ expect(@generic_dal.get_relation_query_sql(rel,{})).to eq(
662
+ "SELECT `a`.`code_alpha_2`,`a`.`name`,`b`.`code` AS `_table_key` FROM `countries` AS `a`, `currencies` AS `b` WHERE (`a`.`default_currency_code` = `b`.`code`)"
663
+ )
664
+
665
+ end
666
+
667
+ it 'should return the correct sql for a has_one relation with a query' do
668
+
669
+ @generic_dal.table_name = "currencies"
670
+
671
+ rel = {
672
+ :type => :has_one,
673
+ :table => 'countries',
674
+ :table_key => 'default_currency_code',
675
+ :this_key => 'code',
676
+ :table_fields => 'code_alpha_2,name',
677
+ }
678
+
679
+ expect(@generic_dal.get_relation_query_sql(rel,{'testfield'=>1})).to eq(
680
+ "SELECT `a`.`code_alpha_2`,`a`.`name`,`b`.`code` AS `_table_key` FROM `countries` AS `a`, `currencies` AS `b` WHERE (`a`.`default_currency_code` = `b`.`code`) AND (`b`.`testfield` = 1)"
681
+ )
682
+
683
+ end
684
+
685
+ it 'should return the correct sql for a has_many relation' do
686
+
687
+ @generic_dal.table_name = "houses"
688
+
689
+ rel = {
690
+ :type => :has_many,
691
+ :table => 'cats',
692
+ :table_key => 'house_id',
693
+ :this_key => 'id',
694
+ :table_fields => 'cat_id,name',
695
+ }
696
+
697
+ expect(@generic_dal.get_relation_query_sql(rel,{})).to eq(
698
+ "SELECT `a`.`cat_id`,`a`.`name`,`b`.`id` AS `_table_key` FROM `cats` AS `a`, `houses` AS `b` WHERE (`a`.`house_id` = `b`.`id`)"
699
+ )
700
+
701
+ end
702
+
703
+ it 'should return the correct sql for a has_many relation with a query' do
704
+
705
+ @generic_dal.table_name = "houses"
706
+
707
+ rel = {
708
+ :type => :has_many,
709
+ :table => 'cats',
710
+ :table_key => 'house_id',
711
+ :this_key => 'id',
712
+ :table_fields => 'cat_id,name',
713
+ }
714
+
715
+ expect(@generic_dal.get_relation_query_sql(rel,{"colour"=>"ginger"})).to eq(
716
+ "SELECT `a`.`cat_id`,`a`.`name`,`b`.`id` AS `_table_key` FROM `cats` AS `a`, `houses` AS `b` WHERE (`a`.`house_id` = `b`.`id`) AND (`b`.`colour` = 'ginger')"
717
+ )
718
+
719
+ end
720
+
721
+ it 'should return the correct sql for a has_many_through relation' do
722
+
723
+ @generic_dal.table_name = "countries"
724
+
725
+ rel = {
726
+ :type => :has_many_through,
727
+ :table => 'regions',
728
+ :link_table => 'region_countries',
729
+ :link_key => 'country_code_alpha_2',
730
+ :link_field => 'region_code',
731
+ :table_key => 'code',
732
+ :this_key => 'code_alpha_2',
733
+ :table_fields => 'code,name',
734
+ }
735
+
736
+ expect(@generic_dal.get_relation_query_sql(rel,{})).to eq(
737
+ "SELECT `a`.`code`,`a`.`name`,`c`.`code_alpha_2` AS `_table_key` FROM `regions` AS `a`, `region_countries` AS `b`, `countries` AS `c` WHERE (`a`.`code` = `b`.`region_code` AND `b`.`country_code_alpha_2` = `c`.`code_alpha_2`)"
738
+ )
739
+
740
+ end
741
+
742
+ it 'should return the correct sql for a has_many_through relation with a query' do
743
+
744
+ @generic_dal.table_name = "countries"
745
+
746
+ rel = {
747
+ :type => :has_many_through,
748
+ :table => 'regions',
749
+ :link_table => 'region_countries',
750
+ :link_key => 'country_code_alpha_2',
751
+ :link_field => 'region_code',
752
+ :table_key => 'code',
753
+ :this_key => 'code_alpha_2',
754
+ :table_fields => 'code,name',
755
+ }
756
+
757
+ expect(@generic_dal.get_relation_query_sql(rel,{"default_currency_code"=>"EUR"})).to eq(
758
+ "SELECT `a`.`code`,`a`.`name`,`c`.`code_alpha_2` AS `_table_key` FROM `regions` AS `a`, `region_countries` AS `b`, `countries` AS `c` WHERE (`a`.`code` = `b`.`region_code` AND `b`.`country_code_alpha_2` = `c`.`code_alpha_2`) AND (`c`.`default_currency_code` = 'EUR')"
759
+ )
760
+
761
+ end
762
+
763
+ it 'should return the correct sql for a has_many_through relation with a query' do
764
+
765
+ @generic_dal.table_name = "countries"
766
+
767
+ rel = {
768
+ :type => :unknown,
769
+ :table => 'regions',
770
+ :link_table => 'region_countries',
771
+ :link_key => 'country_code_alpha_2',
772
+ :link_field => 'region_code',
773
+ :table_key => 'code',
774
+ :this_key => 'code_alpha_2',
775
+ :table_fields => 'code,name',
776
+ }
777
+
778
+ expect(@mock_log).to receive(:error).with("Relation type unknown undefined!")
779
+
780
+ expect(@generic_dal.get_relation_query_sql(rel,{"default_currency_code"=>"EUR"})).to be_nil()
781
+
782
+ end
783
+ end
784
+
785
+ describe "#get_relation_tables" do
786
+ it 'should return the correct tables for a has_one relation' do
787
+ @generic_dal.table_name = "currencies"
788
+
789
+ rel = {
790
+ :type => :has_one,
791
+ :table => 'countries',
792
+ :table_key => 'default_currency_code',
793
+ :this_key => 'code',
794
+ :table_fields => 'code_alpha_2,name',
795
+ }
796
+
797
+ expect(@generic_dal.get_relation_tables(rel)).to eq(["countries", "currencies"])
798
+ end
799
+
800
+ it 'should return the correct tables for a has_many relation' do
801
+ @generic_dal.table_name = "houses"
802
+
803
+ rel = {
804
+ :type => :has_many,
805
+ :table => 'cats',
806
+ :table_key => 'house_id',
807
+ :this_key => 'id',
808
+ :table_fields => 'cat_id,name',
809
+ }
810
+
811
+ expect(@generic_dal.get_relation_tables(rel)).to eq(["cats", "houses"])
812
+ end
813
+
814
+ it 'should return the correct tables for a has_many_through relation' do
815
+ @generic_dal.table_name = "countries"
816
+
817
+ rel = {
818
+ :type => :has_many_through,
819
+ :table => 'regions',
820
+ :link_table => 'region_countries',
821
+ :link_key => 'country_code_alpha_2',
822
+ :link_field => 'region_code',
823
+ :table_key => 'code',
824
+ :this_key => 'code_alpha_2',
825
+ :table_fields => 'code,name',
826
+ }
827
+
828
+ expect(@generic_dal.get_relation_tables(rel)).to eq(["countries","region_countries","regions"])
829
+ end
830
+
831
+ it 'should throw if unknown relation' do
832
+ @generic_dal.table_name = "countries"
833
+
834
+ rel = {
835
+ :type => :unknown,
836
+ }
837
+
838
+ expect{@generic_dal.get_relation_tables(rel)}.to raise_error("Unknown Relation type unknown")
839
+ end
840
+ end
841
+
842
+ describe '#expire_table_cache' do
843
+ it 'should set a table version when it doesnt exist' do
844
+
845
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(nil)
846
+ expect(@mock_memcache).to receive(:set).ordered.with("prefix-testtable-version",1,nil,{:raw=>true}).and_return(nil)
847
+
848
+ @generic_dal.expire_table_cache(['testtable'])
849
+ end
850
+
851
+ it 'should increment a table version when it exists' do
852
+
853
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(1)
854
+ expect(@mock_memcache).to receive(:incr).ordered.with("prefix-testtable-version",1,nil).and_return(nil)
855
+
856
+ @generic_dal.expire_table_cache(['testtable'])
857
+ end
858
+
859
+ it 'should expire multiple tables' do
860
+
861
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-testtable-version").and_return(1)
862
+ expect(@mock_memcache).to receive(:incr).ordered.with("prefix-testtable-version",1,nil).and_return(nil)
863
+ expect(@mock_memcache).to receive(:get).ordered.with("prefix-tabletwo-version").and_return(1)
864
+ expect(@mock_memcache).to receive(:incr).ordered.with("prefix-tabletwo-version",1,nil).and_return(nil)
865
+
866
+ @generic_dal.expire_table_cache(['testtable','tabletwo'])
867
+ end
868
+ end
869
+
870
+ describe '#exists_by_primary_key?' do
871
+ before do
872
+ memcache_null(@mock_memcache)
873
+
874
+ @generic_dal.table_name = 'pktesttable'
875
+ @generic_dal.primary_key = 'id'
876
+
877
+ @mock_result = mysql_result_mock([ { "c" => 1 } ])
878
+ end
879
+
880
+ it 'should call cached_query with correct sql with a numeric primary key' do
881
+ expect(@mock_mysql).to receive(:query).with("SELECT COUNT(*) AS `c` FROM `pktesttable` WHERE (`id` = 2002)").and_return(@mock_result)
882
+
883
+ expect(@generic_dal.exists_by_primary_key?(2002)).to eq(true)
884
+ end
885
+
886
+ it 'should call cached_query with correct sql with a string primary key' do
887
+ expect(@mock_mysql).to receive(:query).with("SELECT COUNT(*) AS `c` FROM `pktesttable` WHERE (`id` = 'test')").and_return(@mock_result)
888
+
889
+ expect(@generic_dal.exists_by_primary_key?('test')).to eq(true)
890
+ end
891
+
892
+ it 'should return true when count is not 0' do
893
+ @mock_result = mysql_result_mock([ { "c" => 1 } ])
894
+
895
+ expect(@mock_mysql).to receive(:query).with("SELECT COUNT(*) AS `c` FROM `pktesttable` WHERE (`id` = 'test')").and_return(@mock_result)
896
+
897
+ expect(@generic_dal.exists_by_primary_key?('test')).to eq(true)
898
+ end
899
+
900
+ it 'should return false when count is 0' do
901
+ @mock_result = mysql_result_mock([ { "c" => 0 } ])
902
+
903
+ expect(@mock_mysql).to receive(:query).with("SELECT COUNT(*) AS `c` FROM `pktesttable` WHERE (`id` = 'test')").and_return(@mock_result)
904
+
905
+ expect(@generic_dal.exists_by_primary_key?('test')).to eq(false)
906
+ end
907
+ end
908
+
909
+ describe '#valid_insert?' do
910
+ it 'should return false if object nil' do
911
+ expect(@generic_dal.valid_insert?(nil)).to eq(false)
912
+ end
913
+
914
+ it 'should return false if object empty' do
915
+ expect(@generic_dal.valid_insert?({})).to eq(false)
916
+ end
917
+
918
+ it 'should return true if all fields exist' do
919
+ @generic_dal.fields = {
920
+ "one" => { :type=>:string },
921
+ "two" => { :type=>:string },
922
+ }
923
+
924
+ expect(@generic_dal.valid_insert?({ "one"=>"1", "two"=>"2" })).to eq(true)
925
+ end
926
+
927
+ it 'should return false if fields do not exist' do
928
+ @generic_dal.fields = {
929
+ "one" => { :type=>:string },
930
+ "two" => { :type=>:string },
931
+ }
932
+
933
+ expect(@generic_dal.valid_insert?({ "five"=>"1", "two"=>"2" })).to eq(false)
934
+ end
935
+
936
+ it 'should return true if data is within the max length' do
937
+ @generic_dal.fields = {
938
+ "one" => { :type=>:string },
939
+ "two" => { :type=>:string, :length=>4 },
940
+ }
941
+
942
+ expect(@generic_dal.valid_insert?({ "one"=>"1", "two"=>"2" })).to eq(true)
943
+ end
944
+
945
+ it 'should return false if data is greater than the max length' do
946
+ @generic_dal.fields = {
947
+ "one" => { :type=>:string },
948
+ "two" => { :type=>:string, :length=>4 },
949
+ }
950
+
951
+ expect(@generic_dal.valid_insert?({ "one"=>"1", "two"=>"22332" })).to eq(false)
952
+ end
953
+
954
+ it 'should return false if required key is missing' do
955
+ @generic_dal.fields = {
956
+ "one" => { :type=>:string },
957
+ "two" => { :type=>:string, :required=>true },
958
+ }
959
+
960
+ expect(@generic_dal.valid_insert?({ "one"=>"1" })).to eq(false)
961
+ end
962
+
963
+ it 'should return true if required keys are ok' do
964
+ @generic_dal.fields = {
965
+ "one" => { :type=>:string, :required=>true },
966
+ "two" => { :type=>:string, :required=>true },
967
+ }
968
+
969
+ expect(@generic_dal.valid_insert?({ "one"=>"1","two"=>"2" })).to eq(true)
970
+ end
971
+ end
972
+
973
+ describe '#valid_update?' do
974
+ it 'should return false if object nil' do
975
+ expect(@generic_dal.valid_update?(nil)).to eq(false)
976
+ end
977
+
978
+ it 'should return false if object empty' do
979
+ expect(@generic_dal.valid_update?({})).to eq(false)
980
+ end
981
+
982
+ it 'should return true if all fields exist' do
983
+ @generic_dal.fields = {
984
+ "one" => { :type=>:string },
985
+ "two" => { :type=>:string },
986
+ }
987
+
988
+ expect(@generic_dal.valid_update?({ "one"=>"1", "two"=>"2" })).to eq(true)
989
+ end
990
+
991
+ it 'should return false if fields do not exist' do
992
+ @generic_dal.fields = {
993
+ "one" => { :type=>:string },
994
+ "two" => { :type=>:string },
995
+ }
996
+
997
+ expect(@generic_dal.valid_update?({ "five"=>"1", "two"=>"2" })).to eq(false)
998
+ end
999
+
1000
+ it 'should return false if data is greater than the max length' do
1001
+ @generic_dal.fields = {
1002
+ "one" => { :type=>:string },
1003
+ "two" => { :type=>:string, :length=>4 },
1004
+ }
1005
+
1006
+ expect(@generic_dal.valid_update?({ "one"=>"1", "two"=>"22332" })).to eq(false)
1007
+ end
1008
+ end
1009
+
1010
+ describe "#escape_value" do
1011
+ it 'should return NULL for nil' do
1012
+ expect(@generic_dal.escape_value(nil)).to eq('NULL')
1013
+ end
1014
+
1015
+ it 'should return integer for int/float' do
1016
+ expect(@generic_dal.escape_value(1)).to eq('1')
1017
+ expect(@generic_dal.escape_value(1.45)).to eq('1.45')
1018
+ end
1019
+
1020
+ it 'should return a quoted string for string' do
1021
+ expect(@generic_dal.escape_value('test')).to eq("'test'")
1022
+ end
1023
+
1024
+ it 'should escape sql values properly' do
1025
+ expect(@generic_dal.escape_value("test '; DROP TABLE test; --")).to eq("'test \\'; DROP TABLE test; --'")
1026
+ end
1027
+ end
1028
+
1029
+ describe "#build_insert" do
1030
+ it 'should return correct SQL fragment for basic fields' do
1031
+ data = {
1032
+ "one" => 1,
1033
+ "two" => "2",
1034
+ "three" => nil,
1035
+ }
1036
+
1037
+ expect(@generic_dal.build_insert(data)).to eq("(`one`, `two`, `three`) VALUES (1, '2', NULL)")
1038
+ end
1039
+
1040
+ it 'should escape field names and data' do
1041
+ data = {
1042
+ "one`; DROP TABLE test; -- " => 1,
1043
+ "two" => "two",
1044
+ "three" => "'; DROP TABLE test; --'",
1045
+ }
1046
+
1047
+ expect(@generic_dal.build_insert(data)).to eq("(`one; DROP TABLE test; -- `, `two`, `three`) VALUES (1, 'two', '\\'; DROP TABLE test; --\\'')")
1048
+ end
1049
+ end
1050
+
1051
+ describe "#build_update" do
1052
+ it 'should return correct SQL fragment for basic fields' do
1053
+ data = {
1054
+ "one" => 1,
1055
+ "two" => "two",
1056
+ "three" => nil,
1057
+ }
1058
+
1059
+ expect(@generic_dal.build_update(data)).to eq("`one` = 1, `two` = 'two', `three` = NULL")
1060
+ end
1061
+
1062
+ it 'should escape field names and data' do
1063
+ data = {
1064
+ "one`; DROP TABLE test; -- " => 1,
1065
+ "two" => "2",
1066
+ "three" => "'; DROP TABLE test; --'",
1067
+ }
1068
+
1069
+ expect(@generic_dal.build_update(data)).to eq("`one; DROP TABLE test; -- ` = 1, `two` = '2', `three` = '\\'; DROP TABLE test; --\\''")
1070
+ end
1071
+ end
1072
+
1073
+ describe "#get_all_related_tables" do
1074
+ it 'should return the table name for nil relations' do
1075
+ @generic_dal.table_name = 'test1'
1076
+
1077
+ @generic_dal.relations = nil
1078
+
1079
+ expect(@generic_dal.get_all_related_tables).to eq(["test1"])
1080
+ end
1081
+
1082
+ it 'should return the table name for empty relations' do
1083
+ @generic_dal.table_name = 'test1'
1084
+
1085
+ @generic_dal.relations = {}
1086
+
1087
+ expect(@generic_dal.get_all_related_tables).to eq(["test1"])
1088
+ end
1089
+
1090
+ it 'should return the table name for a single relations' do
1091
+ @generic_dal.table_name = 'test1'
1092
+
1093
+ @generic_dal.relations = {
1094
+ 'countries' => {
1095
+ :type => :has_one,
1096
+ :table => 'countries',
1097
+ :table_key => 'default_currency_code',
1098
+ :this_key => 'code',
1099
+ :table_fields => 'code_alpha_2,name',
1100
+ },
1101
+ }
1102
+
1103
+ expect(@generic_dal.get_all_related_tables).to eq(["countries","test1"])
1104
+ end
1105
+
1106
+
1107
+ it 'should return the correct table names for multiple relations with dedupe' do
1108
+ @generic_dal.table_name = 'test1'
1109
+
1110
+ @generic_dal.relations = {
1111
+ 'countries' => {
1112
+ :type => :has_one,
1113
+ :table => 'countries',
1114
+ :table_key => 'default_currency_code',
1115
+ :this_key => 'code',
1116
+ :table_fields => 'code_alpha_2,name',
1117
+ },
1118
+ 'countries2' => {
1119
+ :type => :has_many,
1120
+ :table => 'countries',
1121
+ :table_key => 'default_currency_code',
1122
+ :this_key => 'code',
1123
+ :table_fields => 'code_alpha_2,name',
1124
+ },
1125
+ 'regions' => {
1126
+ :type => :has_many_through,
1127
+ :table => 'regions',
1128
+ :link_table => 'region_countries',
1129
+ :link_key => 'country_code_alpha_2',
1130
+ :link_field => 'region_code',
1131
+ :table_key => 'code',
1132
+ :this_key => 'code_alpha_2',
1133
+ :table_fields => 'code,name',
1134
+ }
1135
+ }
1136
+
1137
+ expect(@generic_dal.get_all_related_tables).to eq(["countries", "region_countries", "regions", "test1"])
1138
+ end
1139
+ end
1140
+
1141
+ describe '#insert' do
1142
+ it 'should call the correct sql and expire the correct cache' do
1143
+ testdata = { "field_one" => "one" }
1144
+
1145
+ @generic_dal.table_name = "test_table"
1146
+ @generic_dal.fields = {
1147
+ "field_one" => { :type => :integer }
1148
+ }
1149
+ @generic_dal.auto_primary_key = false
1150
+
1151
+ query = "INSERT INTO `test_table` (`field_one`) VALUES ('one')"
1152
+
1153
+ expect(@mock_mysql).to receive(:query).ordered.with(query)
1154
+ expect(@mock_mysql).not_to receive(:last_id)
1155
+
1156
+ expect(@mock_memcache).to receive(:get).ordered.with('prefix-test_table-version').and_return(1)
1157
+ expect(@mock_memcache).to receive(:incr).ordered.with('prefix-test_table-version',1,nil)
1158
+
1159
+ expect(@mock_memcache).to receive(:get).ordered.with('prefix-test_table-version').and_return(1)
1160
+ expect(@mock_memcache).to receive(:get).ordered.and_return([{ "field_one" => "one","id"=>1 }])
1161
+
1162
+ @generic_dal.insert(testdata)
1163
+ end
1164
+
1165
+ it 'should call last_id when auto_primary_key is true' do
1166
+ testdata = { "field_one" => "one" }
1167
+
1168
+ @generic_dal.table_name = "test_table"
1169
+ @generic_dal.fields = {
1170
+ "field_one" => { :type => :integer }
1171
+ }
1172
+ @generic_dal.auto_primary_key = true
1173
+
1174
+ query = "INSERT INTO `test_table` (`field_one`) VALUES ('one')"
1175
+
1176
+ expect(@mock_mysql).to receive(:query).ordered.with(query)
1177
+ expect(@mock_mysql).to receive(:last_id)
1178
+
1179
+ expect(@mock_memcache).to receive(:get).ordered.with('prefix-test_table-version').and_return(1)
1180
+ expect(@mock_memcache).to receive(:incr).ordered.with('prefix-test_table-version',1,nil)
1181
+
1182
+ expect(@mock_memcache).to receive(:get).ordered.with('prefix-test_table-version').and_return(1)
1183
+ expect(@mock_memcache).to receive(:get).ordered.and_return([{ "field_one" => "one","id"=>1 }])
1184
+ expect(@mock_memcache).not_to receive(:last_id)
1185
+
1186
+ @generic_dal.insert(testdata)
1187
+ end
1188
+
1189
+ it 'should log to error when insert fails' do
1190
+ testdata = { "field_one" => "one" }
1191
+
1192
+ @generic_dal.table_name = "test_table"
1193
+ @generic_dal.fields = {
1194
+ "field_one" => { :type => :integer }
1195
+ }
1196
+ @generic_dal.auto_primary_key = true
1197
+
1198
+ query = "INSERT INTO `test_table` (`field_one`) VALUES ('one')"
1199
+
1200
+ expect(@mock_mysql).to receive(:query) { raise "TestException" }
1201
+
1202
+ expect(@generic_dal).not_to receive(:get_one)
1203
+ expect(@mock_log).to receive(:error).with("TestException")
1204
+
1205
+ expect(@generic_dal.insert(testdata)).to be_nil()
1206
+ end
1207
+ end
1208
+
1209
+ describe '#update_by_primary_key' do
1210
+ it 'should call the correct sql and expire the correct cache' do
1211
+ testdata = { "field_one" => "two" }
1212
+
1213
+ @generic_dal.table_name = "test_table"
1214
+ @generic_dal.primary_key = "code"
1215
+ @generic_dal.fields = {
1216
+ "field_one" => { :type => :integer }
1217
+ }
1218
+
1219
+ query = "UPDATE `test_table` SET `field_one` = 'two' WHERE (`code` = 2)"
1220
+
1221
+ expect(@mock_mysql).to receive(:query).ordered.with(query)
1222
+
1223
+ expect(@mock_memcache).to receive(:get).ordered.with('prefix-test_table-version').and_return(1)
1224
+ expect(@mock_memcache).to receive(:incr).ordered.with('prefix-test_table-version',1,nil)
1225
+
1226
+ expect(@mock_memcache).to receive(:get).ordered.with('prefix-test_table-version').and_return(1)
1227
+ expect(@mock_memcache).to receive(:get).ordered.and_return([{ "field_one" => "two","id"=>2}])
1228
+
1229
+ @generic_dal.update_by_primary_key(2, testdata)
1230
+ end
1231
+
1232
+ it 'should log to error when db update fails' do
1233
+ testdata = { "field_one" => "two" }
1234
+
1235
+ @generic_dal.table_name = "test_table"
1236
+ @generic_dal.primary_key = "code"
1237
+ @generic_dal.fields = {
1238
+ "field_one" => { :type => :integer }
1239
+ }
1240
+
1241
+ query = "UPDATE `test_table` SET `field_one` = 'two' WHERE (`code` = 2)"
1242
+
1243
+ expect(@mock_mysql).to receive(:query) { raise "TestException" }
1244
+ expect(@generic_dal).not_to receive(:get_one)
1245
+ expect(@mock_log).to receive(:error).with("TestException")
1246
+
1247
+ expect(@generic_dal.update_by_primary_key(2, testdata)).to eq(false)
1248
+ end
1249
+ end
1250
+
1251
+ describe '#delete_by_primary_key' do
1252
+ it 'should call the correct sql and expire the correct cache' do
1253
+
1254
+ @generic_dal.table_name = "test_table"
1255
+ @generic_dal.primary_key = "code"
1256
+
1257
+ query = "DELETE FROM `test_table` WHERE (`code` = 'three')"
1258
+
1259
+ expect(@mock_mysql).to receive(:query).ordered.with(query)
1260
+ expect(@mock_memcache).to receive(:get).ordered.with('prefix-test_table-version').and_return(1)
1261
+ expect(@mock_memcache).to receive(:incr).ordered.with('prefix-test_table-version',1,nil)
1262
+
1263
+ @generic_dal.delete_by_primary_key('three')
1264
+ end
1265
+
1266
+ it 'should log to error when db delete fails' do
1267
+
1268
+ @generic_dal.table_name = "test_table"
1269
+ @generic_dal.primary_key = "code"
1270
+
1271
+ query = "DELETE FROM `test_table` WHERE (`code` = 'three')"
1272
+
1273
+ expect(@mock_mysql).to receive(:query) { raise "TestException" }
1274
+ expect(@generic_dal).not_to receive(:get_one)
1275
+ expect(@mock_log).to receive(:error).with("TestException")
1276
+
1277
+ expect(@generic_dal.delete_by_primary_key('three')).to eq(false)
1278
+ end
1279
+ end
1280
+
1281
+ describe '#get_all_by_query_as_hash' do
1282
+ it 'should call map_to_hash_by_primary_key / get_all_by_query from query' do
1283
+
1284
+ expect(@generic_dal).to receive(:get_all_by_query).with("query").and_return("results")
1285
+ expect(@generic_dal).to receive(:map_to_hash_by_primary_key).with("results").and_return("hashed_results")
1286
+ expect(@generic_dal.get_all_by_query_as_hash("query")).to eq("hashed_results")
1287
+ end
1288
+ end
1289
+
1290
+ describe '#get_relation_data_as_hash' do
1291
+ it 'should return {} if no relations exist' do
1292
+ @generic_dal.relations = nil
1293
+ expect(@generic_dal.get_relation_data_as_hash("query")).to eq({})
1294
+ @generic_dal.relations = {}
1295
+ expect(@generic_dal.get_relation_data_as_hash("query")).to eq({})
1296
+ end
1297
+
1298
+ it 'should call get_includes' do
1299
+ @generic_dal.relations = { "name" => OpenStruct.new()}
1300
+
1301
+ includes = OpenStruct.new()
1302
+ expect(@generic_dal).to receive(:get_includes).with("query").and_return(includes)
1303
+ expect(includes).to receive(:find_index).with("name").and_return(nil)
1304
+
1305
+ expect(@generic_dal.get_relation_data_as_hash("query")).to eq({})
1306
+ end
1307
+
1308
+ it 'should set up correct hash' do
1309
+ @generic_dal.relations = { "testname" => OpenStruct.new()}
1310
+
1311
+ includes = OpenStruct.new()
1312
+ expect(@generic_dal).to receive(:get_includes).with("testquery").and_return(includes)
1313
+ expect(includes).to receive(:find_index).with("testname").and_return(true)
1314
+ expect(@generic_dal).to receive(:get_relation_query_sql).with(includes,"testquery").and_return("testsql")
1315
+ expect(@generic_dal).to receive(:get_relation_tables).with(includes).and_return("tables")
1316
+ expect(@generic_dal).to receive(:cached_query).with("testsql", "tables").and_return("testdata")
1317
+ expect(@generic_dal).to receive(:map_to_hash_of_arrays_by_key).with("testdata", "_table_key").and_return("testreldata")
1318
+ expect(@generic_dal).to receive(:remove_key_from_hash_of_arrays!).with("testreldata", "_table_key").and_return("testreldata")
1319
+
1320
+ expect(@generic_dal.get_relation_data_as_hash("testquery")).to eq({"testname"=>"testreldata"})
1321
+ end
1322
+ end
1323
+
1324
+ describe '#map_in_included_relations!' do
1325
+ it 'should call get_relation_data_as_hash' do
1326
+
1327
+ result = OpenStruct.new
1328
+ expect(@generic_dal).to receive(:get_relation_data_as_hash).with("testquery")
1329
+ expect(result).to receive(:each) {}
1330
+
1331
+ @generic_dal.map_in_included_relations!(result,'testquery')
1332
+ end
1333
+
1334
+ it 'should call get_relation_data_as_hash with generic relation' do
1335
+ @generic_dal.relations = {
1336
+ "one" => { :type=>:string, :this_key => 'one' },
1337
+ }
1338
+
1339
+ dat = { "one" => "test" }
1340
+ results = [ { "one" => 1 } ]
1341
+
1342
+ expect(@generic_dal).to receive(:get_relation_data_as_hash).with("testquery").and_return(dat)
1343
+ @generic_dal.map_in_included_relations!(results,'testquery')
1344
+
1345
+ expect(results[0]).to eq({"one"=>"e"})
1346
+ end
1347
+
1348
+ it 'should call get_relation_data_as_hash with has_one relation' do
1349
+ @generic_dal.relations = {
1350
+ "one" => { :type=>:has_one, :this_key => 'one' },
1351
+ }
1352
+
1353
+ dat = { "one" => "test" }
1354
+ results = [ { "one" => 1 } ]
1355
+
1356
+ expect(@generic_dal).to receive(:get_relation_data_as_hash).with("testquery").and_return(dat)
1357
+ @generic_dal.map_in_included_relations!(results,'testquery')
1358
+
1359
+ expect(results[0]).to eq({"one"=>"e"})
1360
+ end
1361
+ end
1362
+
1363
+ end