arel_extensions 1.2.5 → 1.2.15

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -4
  3. data/.travis.yml +54 -86
  4. data/README.md +7 -2
  5. data/Rakefile +38 -27
  6. data/arel_extensions.gemspec +1 -1
  7. data/functions.html +2 -2
  8. data/gemfiles/rails4.gemfile +1 -1
  9. data/gemfiles/rails6.gemfile +30 -0
  10. data/gemspec_v2/arel_extensions-v2.gemspec +28 -0
  11. data/generate_gems.sh +14 -0
  12. data/lib/arel_extensions.rb +49 -21
  13. data/lib/arel_extensions/attributes.rb +0 -1
  14. data/lib/arel_extensions/boolean_functions.rb +38 -13
  15. data/lib/arel_extensions/common_sql_functions.rb +5 -4
  16. data/lib/arel_extensions/insert_manager.rb +26 -24
  17. data/lib/arel_extensions/math.rb +3 -3
  18. data/lib/arel_extensions/math_functions.rb +4 -4
  19. data/lib/arel_extensions/nodes/abs.rb +0 -0
  20. data/lib/arel_extensions/nodes/case.rb +8 -4
  21. data/lib/arel_extensions/nodes/ceil.rb +0 -0
  22. data/lib/arel_extensions/nodes/coalesce.rb +0 -0
  23. data/lib/arel_extensions/nodes/collate.rb +1 -1
  24. data/lib/arel_extensions/nodes/concat.rb +0 -0
  25. data/lib/arel_extensions/nodes/date_diff.rb +1 -3
  26. data/lib/arel_extensions/nodes/duration.rb +0 -2
  27. data/lib/arel_extensions/nodes/find_in_set.rb +0 -0
  28. data/lib/arel_extensions/nodes/floor.rb +0 -0
  29. data/lib/arel_extensions/nodes/formatted_number.rb +20 -20
  30. data/lib/arel_extensions/nodes/function.rb +0 -0
  31. data/lib/arel_extensions/nodes/is_null.rb +0 -0
  32. data/lib/arel_extensions/nodes/json.rb +43 -30
  33. data/lib/arel_extensions/nodes/length.rb +0 -0
  34. data/lib/arel_extensions/nodes/locate.rb +0 -0
  35. data/lib/arel_extensions/nodes/power.rb +5 -4
  36. data/lib/arel_extensions/nodes/rand.rb +0 -0
  37. data/lib/arel_extensions/nodes/replace.rb +23 -5
  38. data/lib/arel_extensions/nodes/round.rb +5 -5
  39. data/lib/arel_extensions/nodes/soundex.rb +14 -13
  40. data/lib/arel_extensions/nodes/substring.rb +8 -15
  41. data/lib/arel_extensions/nodes/trim.rb +1 -1
  42. data/lib/arel_extensions/nodes/union.rb +0 -1
  43. data/lib/arel_extensions/nodes/union_all.rb +0 -1
  44. data/lib/arel_extensions/nodes/wday.rb +0 -0
  45. data/lib/arel_extensions/predications.rb +35 -33
  46. data/lib/arel_extensions/set_functions.rb +2 -2
  47. data/lib/arel_extensions/string_functions.rb +25 -6
  48. data/lib/arel_extensions/tasks.rb +5 -5
  49. data/lib/arel_extensions/version.rb +1 -1
  50. data/lib/arel_extensions/visitors.rb +1 -1
  51. data/lib/arel_extensions/visitors/ibm_db.rb +1 -1
  52. data/lib/arel_extensions/visitors/mssql.rb +13 -12
  53. data/lib/arel_extensions/visitors/mysql.rb +67 -37
  54. data/lib/arel_extensions/visitors/oracle.rb +14 -14
  55. data/lib/arel_extensions/visitors/oracle12.rb +1 -1
  56. data/lib/arel_extensions/visitors/postgresql.rb +46 -28
  57. data/lib/arel_extensions/visitors/sqlite.rb +52 -44
  58. data/lib/arel_extensions/visitors/to_sql.rb +73 -59
  59. data/test/arelx_test_helper.rb +28 -0
  60. data/test/support/fake_record.rb +4 -0
  61. data/test/test_comparators.rb +8 -7
  62. data/test/visitors/test_bulk_insert_oracle.rb +8 -7
  63. data/test/visitors/test_bulk_insert_sqlite.rb +8 -7
  64. data/test/visitors/test_bulk_insert_to_sql.rb +3 -3
  65. data/test/visitors/test_oracle.rb +41 -41
  66. data/test/visitors/test_to_sql.rb +367 -199
  67. data/test/with_ar/all_agnostic_test.rb +63 -41
  68. data/test/with_ar/insert_agnostic_test.rb +1 -1
  69. data/test/with_ar/test_bulk_sqlite.rb +5 -4
  70. data/test/with_ar/test_math_sqlite.rb +2 -2
  71. data/test/with_ar/test_string_mysql.rb +2 -4
  72. data/test/with_ar/test_string_sqlite.rb +2 -6
  73. data/version_v1.rb +3 -0
  74. data/version_v2.rb +3 -0
  75. metadata +10 -5
  76. data/test/helper.rb +0 -18
@@ -1,6 +1,6 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::SQLite.class_eval do
3
+ class Arel::Visitors::SQLite
4
4
  Arel::Visitors::SQLite::DATE_MAPPING = {'d' => '%d', 'm' => '%m', 'w' => '%W', 'y' => '%Y', 'wd' => '%w', 'M' => '%M', 'h' => '%H', 'mn' => '%M', 's' => '%S'}
5
5
  Arel::Visitors::SQLite::DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
6
6
  '%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
@@ -193,18 +193,28 @@ module ArelExtensions
193
193
  collector
194
194
  end
195
195
 
196
- # CASE WHEN ROUND(3.42,1) > round(3.42) THEN round(3.42) ELSE round(3.42)-1 END
197
- # OR CAST(3.14 AS INTEGER)
196
+ # CAST(
197
+ # CASE
198
+ # WHEN 3.42 >= 0 THEN CAST(3.42 AS INT)
199
+ # WHEN CAST(3.42 AS INT) = 3.42 THEN CAST(3.42 AS INT)
200
+ # ELSE CAST((3.42 - 1.0) AS INT)
201
+ # END
202
+ # AS FLOAT
203
+ # )
198
204
  def visit_ArelExtensions_Nodes_Floor o, collector
199
- collector << "CASE WHEN ROUND("
205
+ collector << "CAST(CASE WHEN "
200
206
  collector = visit o.left, collector
201
- collector << ", 1) > ROUND("
207
+ collector << " >= 0 THEN CAST("
202
208
  collector = visit o.left, collector
203
- collector << ") THEN ROUND("
209
+ collector << " AS INT) WHEN CAST("
210
+ collector = visit o.left, collector
211
+ collector << " AS INT) = "
212
+ collector = visit o.left, collector
213
+ collector << " THEN CAST("
204
214
  collector = visit o.left, collector
205
- collector << ") ELSE ROUND("
215
+ collector << " AS INT) ELSE CAST(("
206
216
  collector = visit o.left, collector
207
- collector << ") - 1 END"
217
+ collector << " - 1.0) AS INT) END AS FLOAT)"
208
218
  collector
209
219
  end
210
220
 
@@ -225,9 +235,8 @@ module ArelExtensions
225
235
  def visit_ArelExtensions_InsertManager_BulkValues o, collector
226
236
  o.left.each_with_index do |row, idx|
227
237
  collector << 'SELECT '
228
- v = Arel::Nodes::Values.new(row, o.cols)
229
- len = v.expressions.length - 1
230
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
238
+ len = row.length - 1
239
+ row.zip(o.cols).each_with_index { |(value, attr), i|
231
240
  case value
232
241
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
233
242
  collector = visit value.as(attr.name), collector
@@ -248,12 +257,17 @@ module ArelExtensions
248
257
  def visit_ArelExtensions_InsertManager_BulkValues o, collector
249
258
  o.left.each_with_index do |row, idx|
250
259
  collector << 'SELECT '
251
- v = Arel::Nodes::Values.new(row, o.cols)
252
- len = v.expressions.length - 1
253
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
260
+ len = row.length - 1
261
+ row.zip(o.cols).each_with_index { |(value, attr), i|
254
262
  case value
255
263
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
256
264
  collector = visit value.as(attr.name), collector
265
+ when Integer
266
+ collector << value.to_s
267
+ if idx == 0
268
+ collector << " AS "
269
+ collector << quote(attr.name)
270
+ end
257
271
  else
258
272
  collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
259
273
  if idx == 0
@@ -270,32 +284,36 @@ module ArelExtensions
270
284
  end
271
285
 
272
286
  def visit_ArelExtensions_Nodes_Union o, collector
273
- if o.left.is_a?(Arel::SelectManager)
274
- collector = visit o.left.ast, collector
275
- else
276
- collector = visit o.left, collector
277
- end
287
+ collector =
288
+ if o.left.is_a?(Arel::SelectManager)
289
+ visit o.left.ast, collector
290
+ else
291
+ visit o.left, collector
292
+ end
278
293
  collector << " UNION "
279
- if o.right.is_a?(Arel::SelectManager)
280
- collector = visit o.right.ast, collector
281
- else
282
- collector = visit o.right, collector
283
- end
294
+ collector =
295
+ if o.right.is_a?(Arel::SelectManager)
296
+ visit o.right.ast, collector
297
+ else
298
+ visit o.right, collector
299
+ end
284
300
  collector
285
301
  end
286
302
 
287
303
  def visit_ArelExtensions_Nodes_UnionAll o, collector
288
- if o.left.is_a?(Arel::SelectManager)
289
- collector = visit o.left.ast, collector
290
- else
291
- collector = visit o.left, collector
292
- end
304
+ collector =
305
+ if o.left.is_a?(Arel::SelectManager)
306
+ visit o.left.ast, collector
307
+ else
308
+ visit o.left, collector
309
+ end
293
310
  collector << " UNION ALL "
294
- if o.right.is_a?(Arel::SelectManager)
295
- collector = visit o.right.ast, collector
296
- else
297
- collector = visit o.right, collector
298
- end
311
+ collector =
312
+ if o.right.is_a?(Arel::SelectManager)
313
+ visit o.right.ast, collector
314
+ else
315
+ visit o.right, collector
316
+ end
299
317
  collector
300
318
  end
301
319
 
@@ -346,16 +364,6 @@ module ArelExtensions
346
364
  collector
347
365
  end
348
366
 
349
-
350
- alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
351
- def visit_Arel_Nodes_SelectStatement o, collector
352
- if !collector.value.blank? && o.limit.blank?
353
- o = o.dup
354
- o.orders = []
355
- end
356
- old_visit_Arel_Nodes_SelectStatement(o,collector)
357
- end
358
-
359
367
  alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
360
368
  def visit_Arel_Nodes_As o, collector
361
369
  if o.left.is_a?(Arel::Nodes::Binary)
@@ -1,6 +1,7 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::ToSql.class_eval do
3
+ class Arel::Visitors::ToSql
4
+ Arel::Visitors::ToSql::COMMA = ', ' unless defined?(Arel::Visitors::ToSql::COMMA)
4
5
 
5
6
  # Math Functions
6
7
  def visit_ArelExtensions_Nodes_Abs o, collector
@@ -134,10 +135,22 @@ module ArelExtensions
134
135
 
135
136
  def visit_ArelExtensions_Nodes_Replace o, collector
136
137
  collector << "REPLACE("
137
- o.expressions.each_with_index { |arg, i|
138
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
139
- collector = visit arg, collector
140
- }
138
+ visit o.left, collector
139
+ collector << Arel::Visitors::ToSql::COMMA
140
+ visit o.pattern, collector
141
+ collector << Arel::Visitors::ToSql::COMMA
142
+ visit o.substitute, collector
143
+ collector << ")"
144
+ collector
145
+ end
146
+
147
+ def visit_ArelExtensions_Nodes_RegexpReplace o, collector
148
+ collector << "REGEXP_REPLACE("
149
+ visit o.left, collector
150
+ collector << Arel::Visitors::ToSql::COMMA
151
+ visit Arel::Nodes.build_quoted(o.pattern.to_s), collector
152
+ collector << Arel::Visitors::ToSql::COMMA
153
+ visit o.substitute, collector
141
154
  collector << ")"
142
155
  collector
143
156
  end
@@ -415,16 +428,15 @@ module ArelExtensions
415
428
  row_nb = o.left.length
416
429
  o.left.each_with_index do |row, idx|
417
430
  collector << '('
418
- v = Arel::Nodes::Values.new(row, o.cols)
419
- len = v.expressions.length - 1
420
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
421
- case value
422
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
423
- collector = visit value, collector
424
- else
425
- collector << quote(value, attr && column_for(attr)).to_s
426
- end
427
- collector << Arel::Visitors::ToSql::COMMA unless i == len
431
+ len = row.length - 1
432
+ row.zip(o.cols).each_with_index { |(value, attr), i|
433
+ case value
434
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
435
+ collector = visit value, collector
436
+ else
437
+ collector << quote(value, attr && column_for(attr)).to_s
438
+ end
439
+ collector << Arel::Visitors::ToSql::COMMA unless i == len
428
440
  }
429
441
  collector << (idx == row_nb-1 ? ')' : '), ')
430
442
  end
@@ -436,16 +448,17 @@ module ArelExtensions
436
448
  row_nb = o.left.length
437
449
  o.left.each_with_index do |row, idx|
438
450
  collector << '('
439
- v = Arel::Nodes::Values.new(row, o.cols)
440
- len = v.expressions.length - 1
441
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
442
- case value
443
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
444
- collector = visit value, collector
445
- else
446
- collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
447
- end
448
- collector << Arel::Visitors::ToSql::COMMA unless i == len
451
+ len = row.length - 1
452
+ row.zip(o.cols).each_with_index { |(value, attr), i|
453
+ case value
454
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
455
+ collector = visit value, collector
456
+ when Integer
457
+ collector << value.to_s
458
+ else
459
+ collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
460
+ end
461
+ collector << Arel::Visitors::ToSql::COMMA unless i == len
449
462
  }
450
463
  collector << (idx == row_nb-1 ? ')' : '), ')
451
464
  end
@@ -530,53 +543,66 @@ module ArelExtensions
530
543
  collector
531
544
  end
532
545
 
546
+ # Boolean logic.
547
+
533
548
  alias_method :old_visit_Arel_Nodes_And, :visit_Arel_Nodes_And
534
549
  def visit_Arel_Nodes_And o, collector
535
- collector << '('
536
550
  case o.children.length
537
551
  when 0
538
- collector << '1=1' # but this should not happen
552
+ collector << '1 = 1' # but this should not happen
539
553
  when 1
540
554
  collector = visit o.children[0], collector
541
555
  else
556
+ collector << '('
542
557
  o.children.each_with_index { |arg, i|
543
558
  if i != 0
544
559
  collector << ') AND ('
545
560
  end
546
561
  collector = visit arg, collector
547
562
  }
563
+ collector << ')'
548
564
  end
549
- collector << ')'
550
565
  collector
551
566
  end
552
567
 
553
- def visit_ArelExtensions_Nodes_Or o, collector
554
- collector << '('
568
+ alias_method :old_visit_Arel_Nodes_Or, :visit_Arel_Nodes_Or
569
+ def visit_Arel_Nodes_Or o, collector
555
570
  case o.children.length
556
571
  when 0
557
- collector << '0=1' # but this should not happen
572
+ collector << '1 = 0' # but this should not happen
558
573
  when 1
559
574
  collector = visit o.children[0], collector
560
575
  else
576
+ collector << '('
561
577
  o.children.each_with_index { |arg, i|
562
578
  if i != 0
563
579
  collector << ') OR ('
564
580
  end
565
581
  collector = visit arg, collector
566
582
  }
583
+ collector << ')'
567
584
  end
568
- collector << ')'
569
585
  collector
570
586
  end
571
587
 
572
- alias_method :old_visit_Arel_Nodes_Or, :visit_Arel_Nodes_Or
573
- def visit_Arel_Nodes_Or o, collector
574
- collector << '('
575
- collector = visit o.left, collector
576
- collector << ') OR ('
577
- collector = visit o.right, collector
578
- collector << ')'
579
- collector
588
+ def json_value(o,v)
589
+ case o.type_of_node(v)
590
+ when :string
591
+ Arel.when(v.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + v.replace('\\','\\\\').replace('"','\"') + '"')
592
+ when :date
593
+ s = v.format('%Y-%m-%d')
594
+ Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
595
+ when :datetime
596
+ s = v.format('%Y-%m-%dT%H:%M:%S')
597
+ Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
598
+ when :time
599
+ s = v.format('%H:%M:%S')
600
+ Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
601
+ when :nil
602
+ Arel::Nodes.build_quoted("null")
603
+ else
604
+ ArelExtensions::Nodes::Cast.new([v, :string]).coalesce("null")
605
+ end
580
606
  end
581
607
 
582
608
  def visit_ArelExtensions_Nodes_Json o,collector
@@ -587,11 +613,7 @@ module ArelExtensions
587
613
  if i != 0
588
614
  res += ', '
589
615
  end
590
- if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.return_type == :string)
591
- res = res + '"' + v + '"'
592
- else
593
- res += v
594
- end
616
+ res += json_value(o,v)
595
617
  end
596
618
  res += ']'
597
619
  collector = visit res, collector
@@ -601,12 +623,8 @@ module ArelExtensions
601
623
  if i != 0
602
624
  res += ', '
603
625
  end
604
- res += Arel::Nodes.build_quoted('"')+k + '": '
605
- if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.respond_to?(:return_type) && v.return_type == :string)
606
- res = res + '"' + v + '"'
607
- else
608
- res += v
609
- end
626
+ res += Arel::Nodes.build_quoted('"') + ArelExtensions::Nodes::Cast.new([k, :string]).coalesce("").replace('\\','\\\\').replace('"','\"') + '": '
627
+ res += json_value(o,v)
610
628
  end
611
629
  res += '}'
612
630
  collector = visit res, collector
@@ -618,7 +636,7 @@ module ArelExtensions
618
636
 
619
637
  def visit_ArelExtensions_Nodes_JsonGroup o, collector
620
638
  if o.as_array
621
- res = Arel::Nodes.build_quoted('[') + (o.orders ? o.dict.group_concat(', ',o.orders) : o.dict.group_concat(', ')) + ']'
639
+ res = Arel::Nodes.build_quoted('[') + (o.orders ? o.dict.group_concat(', ', order: Array(o.orders)) : o.dict.group_concat(', ')).coalesce('') + ']'
622
640
  collector = visit res, collector
623
641
  else
624
642
  res = Arel::Nodes.build_quoted('{')
@@ -627,13 +645,9 @@ module ArelExtensions
627
645
  if i != 0
628
646
  res = res + ', '
629
647
  end
630
- kv = Arel::Nodes.build_quoted('"')+k + '": '
631
- if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.respond_to?(:return_type) && v.return_type == :string)
632
- kv = kv + '"' + v + '"'
633
- else
634
- kv += v
635
- end
636
- res = res + kv.group_concat(', ',orders)
648
+ kv = Arel::Nodes.build_quoted('"') + ArelExtensions::Nodes::Cast.new([k, :string]).coalesce("").replace('\\','\\\\').replace('"','\"') + '": '
649
+ kv += json_value(o,v)
650
+ res = res + kv.group_concat(', ', order: Array(orders)).coalesce('')
637
651
  end
638
652
  res = res + '}'
639
653
  collector = visit res, collector
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'minitest/autorun'
3
+ require 'fileutils'
4
+ require 'arel'
5
+ require 'active_record'
6
+
7
+ require 'support/fake_record'
8
+
9
+ require 'arel_extensions'
10
+ Arel::Table.engine = FakeRecord::Base.new
11
+
12
+ $arel_silence_type_casting_deprecation = true
13
+
14
+ module Minitest::Assertions
15
+ #
16
+ # Fails unless +expected and +actual are the same string, modulo extraneous spaces.
17
+ #
18
+ def assert_like(expected, actual, msg = nil)
19
+ msg ||= "Expected #{expected.inspect} and #{actual.inspect} to be alike"
20
+ assert_equal expected.gsub(/\s+/, ' ').strip, actual.gsub(/\s+/, ' ').strip
21
+ end
22
+ end
23
+
24
+ module Minitest::Expectations
25
+
26
+ infect_an_assertion :assert_like, :must_be_like
27
+
28
+ end
@@ -65,6 +65,10 @@ module FakeRecord
65
65
  self
66
66
  end
67
67
 
68
+ def in_clause_length
69
+ 10000
70
+ end
71
+
68
72
  def quote thing, column = nil
69
73
  if column && !thing.nil?
70
74
  case column.type
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require 'arelx_test_helper'
2
2
 
3
3
  module ArelExtensions
4
4
  module Nodes
@@ -20,26 +20,27 @@ module ArelExtensions
20
20
  end
21
21
 
22
22
  it "< is equal lt" do
23
- compile(@table[:id] < 10).must_be_like('"users"."id" < 10')
23
+ _(compile(@table[:id] < 10)).must_be_like('"users"."id" < 10')
24
24
  end
25
25
 
26
26
  it "<= is equal lteq" do
27
- compile(@table[:id] <= 10).must_be_like('"users"."id" <= 10')
27
+ _(compile(@table[:id] <= 10)).must_be_like('"users"."id" <= 10')
28
28
  end
29
29
 
30
30
  it "> is equal gt" do
31
- compile(@table[:id] > 10).must_be_like('"users"."id" > 10')
31
+ _(compile(@table[:id] > 10)).must_be_like('"users"."id" > 10')
32
32
  end
33
33
 
34
34
  it "< is equal gteq" do
35
- compile(@table[:id] >= 10).must_be_like('"users"."id" >= 10')
35
+ _(compile(@table[:id] >= 10)).must_be_like('"users"."id" >= 10')
36
36
  end
37
37
 
38
38
  it "should compare with dates" do
39
- compile(@table[:created_at] >= Date.new(2016, 3, 31)).must_be_like %{"users"."created_at" >= '2016-03-31'}
39
+ _(compile(@table[:created_at] >= Date.new(2016, 3, 31)))
40
+ .must_be_like %{"users"."created_at" >= '2016-03-31'}
40
41
  end
41
42
 
42
43
  end
43
44
 
44
45
  end
45
- end
46
+ end