crud-service 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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