arel_extensions 2.1.4 → 2.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +162 -222
  3. data/.gitignore +7 -6
  4. data/.rubocop.yml +37 -0
  5. data/Gemfile +3 -3
  6. data/NEWS.md +15 -0
  7. data/README.md +119 -75
  8. data/appveyor.yml +82 -0
  9. data/arel_extensions.gemspec +0 -1
  10. data/gemfiles/rails3.gemfile +5 -5
  11. data/gemfiles/rails4_2.gemfile +38 -0
  12. data/gemfiles/{rails5_0.gemfile → rails5.gemfile} +6 -6
  13. data/gemfiles/rails5_1_4.gemfile +6 -6
  14. data/gemfiles/rails5_2.gemfile +6 -5
  15. data/gemfiles/rails6.gemfile +5 -4
  16. data/gemfiles/rails6_1.gemfile +5 -4
  17. data/gemfiles/rails7.gemfile +5 -4
  18. data/gemspecs/arel_extensions-v1.gemspec +0 -1
  19. data/gemspecs/arel_extensions-v2.gemspec +0 -1
  20. data/lib/arel_extensions/common_sql_functions.rb +2 -2
  21. data/lib/arel_extensions/helpers.rb +12 -12
  22. data/lib/arel_extensions/math.rb +32 -17
  23. data/lib/arel_extensions/nodes/case.rb +4 -3
  24. data/lib/arel_extensions/nodes/cast.rb +2 -2
  25. data/lib/arel_extensions/nodes/coalesce.rb +1 -1
  26. data/lib/arel_extensions/nodes/collate.rb +1 -1
  27. data/lib/arel_extensions/nodes/date_diff.rb +6 -6
  28. data/lib/arel_extensions/nodes/locate.rb +1 -1
  29. data/lib/arel_extensions/nodes/repeat.rb +2 -2
  30. data/lib/arel_extensions/nodes/rollup.rb +36 -0
  31. data/lib/arel_extensions/nodes/select.rb +10 -0
  32. data/lib/arel_extensions/nodes/substring.rb +1 -1
  33. data/lib/arel_extensions/nodes/then.rb +1 -1
  34. data/lib/arel_extensions/nodes/trim.rb +2 -2
  35. data/lib/arel_extensions/nodes/union.rb +3 -3
  36. data/lib/arel_extensions/nodes/union_all.rb +2 -2
  37. data/lib/arel_extensions/null_functions.rb +16 -0
  38. data/lib/arel_extensions/string_functions.rb +1 -0
  39. data/lib/arel_extensions/version.rb +1 -1
  40. data/lib/arel_extensions/visitors/ibm_db.rb +1 -1
  41. data/lib/arel_extensions/visitors/mssql.rb +123 -17
  42. data/lib/arel_extensions/visitors/mysql.rb +78 -11
  43. data/lib/arel_extensions/visitors/oracle.rb +39 -17
  44. data/lib/arel_extensions/visitors/postgresql.rb +17 -12
  45. data/lib/arel_extensions/visitors/sqlite.rb +4 -4
  46. data/lib/arel_extensions/visitors/to_sql.rb +4 -1
  47. data/lib/arel_extensions/visitors.rb +8 -0
  48. data/lib/arel_extensions.rb +26 -0
  49. data/test/arelx_test_helper.rb +1 -1
  50. data/test/real_db_test.rb +5 -5
  51. data/test/support/fake_record.rb +1 -1
  52. data/test/visitors/test_bulk_insert_oracle.rb +3 -3
  53. data/test/visitors/test_bulk_insert_sqlite.rb +1 -1
  54. data/test/visitors/test_bulk_insert_to_sql.rb +1 -1
  55. data/test/visitors/test_to_sql.rb +6 -6
  56. data/test/with_ar/all_agnostic_test.rb +177 -70
  57. data/test/with_ar/insert_agnostic_test.rb +3 -3
  58. data/test/with_ar/test_bulk_sqlite.rb +1 -1
  59. data/version_v1.rb +1 -1
  60. data/version_v2.rb +1 -1
  61. metadata +8 -18
  62. data/gemfiles/rails4.gemfile +0 -29
@@ -73,6 +73,8 @@ module ArelExtensions
73
73
  @neg = User.where(id: u.id)
74
74
  u = User.create age: 15, name: 'Justin', created_at: d, score: 11.0
75
75
  @justin = User.where(id: u.id)
76
+ u = User.create age: nil, name: 'nilly', created_at: nil, score: nil
77
+ @nilly = User.where(id: u.id)
76
78
 
77
79
  @age = User.arel_table[:age]
78
80
  @name = User.arel_table[:name]
@@ -149,7 +151,7 @@ module ArelExtensions
149
151
  def test_rand
150
152
  assert 42 != User.select(Arel.rand.as('res')).first.res
151
153
  assert 0 <= User.select(Arel.rand.abs.as('res')).first.res
152
- assert_equal 9, User.order(Arel.rand).limit(50).count
154
+ assert_equal 10, User.order(Arel.rand).limit(50).count
153
155
  end
154
156
 
155
157
  def test_round
@@ -186,6 +188,49 @@ module ArelExtensions
186
188
  assert User.group(:score).count(:id).values.all?{|e| !e.nil?}
187
189
  end
188
190
 
191
+ def test_rollup
192
+ skip "sqlite not supported" if $sqlite
193
+ at = User.arel_table
194
+ # single
195
+ q = User.select(at[:name], at[:age].sum).group(Arel::Nodes::RollUp.new([at[:name]]))
196
+ assert q.to_a.length > 0
197
+
198
+ # multi
199
+ q = User.select(at[:name], at[:score], at[:age].sum).group(Arel::Nodes::RollUp.new([at[:score], at[:name]]))
200
+ assert q.to_a.length > 0
201
+
202
+ # hybrid
203
+ q = User.select(at[:name], at[:score], at[:age].sum).group(at[:score], Arel::Nodes::RollUp.new([at[:name]]))
204
+ assert q.to_a.length > 0
205
+
206
+ ## Using Arel.rollup which is less verbose than the original way
207
+
208
+ # simple
209
+ q = User.select(at[:name], at[:age].sum).group(Arel.rollup(at[:name]))
210
+ assert q.to_a.length > 0
211
+
212
+ # multi
213
+ q = User.select(at[:name], at[:score], at[:age].sum).group(Arel.rollup([at[:score], at[:name]]))
214
+ assert q.to_a.length > 0
215
+
216
+ # hybrid
217
+ q = User.select(at[:name], at[:score], at[:age].sum).group(at[:score], Arel.rollup([at[:name]]))
218
+ assert q.to_a.length > 0
219
+
220
+ ## Using at[:col].rollup which is handy for single column rollups
221
+
222
+ # simple
223
+ q = User.select(at[:name], at[:age].sum).group(at[:name].rollup)
224
+ assert q.to_a.length > 0
225
+
226
+ q = User.select(at[:name], at[:score], at[:age].sum).group(at[:name].rollup, at[:score].rollup)
227
+ assert q.to_a.length > 0
228
+
229
+ # hybrid
230
+ q = User.select(at[:name], at[:score], at[:age].sum).group(at[:name], at[:score].rollup)
231
+ assert q.to_a.length > 0
232
+ end
233
+
189
234
  # String Functions
190
235
  def test_concat
191
236
  assert_equal 'Camille Camille', t(@camille, @name + ' ' + @name)
@@ -193,16 +238,16 @@ module ArelExtensions
193
238
  assert_equal 'Test Laure', t(@laure, Arel.quoted('Test ') + @name)
194
239
 
195
240
  skip 'No group_concat in SqlServer before 2017' if @env_db == 'mssql'
196
- assert_equal 'Lucas Sophie', t(User.where(name: ['Lucas', 'Sophie']), @name.group_concat(' '))
197
- assert_equal 'Lucas,Sophie', t(User.where(name: ['Lucas', 'Sophie']), @name.group_concat(','))
198
- assert_equal 'Lucas,Sophie', t(User.where(name: ['Lucas', 'Sophie']), @name.group_concat)
241
+ assert_equal 'Lucas Sophie', t(User.where(name: %w[Lucas Sophie]), @name.group_concat(' '))
242
+ assert_equal 'Lucas,Sophie', t(User.where(name: %w[Lucas Sophie]), @name.group_concat(','))
243
+ assert_equal 'Lucas,Sophie', t(User.where(name: %w[Lucas Sophie]), @name.group_concat)
199
244
 
200
245
  skip 'No order in group_concat in SqlLite' if $sqlite
201
- assert_equal 'Arthur,Lucas,Sophie', t(User.where(name: ['Lucas', 'Sophie', 'Arthur']), @name.group_concat(',', @name.asc))
202
- assert_equal 'Sophie,Lucas,Arthur', t(User.where(name: ['Lucas', 'Sophie', 'Arthur']), @name.group_concat(',', @name.desc))
203
- assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: ['Lucas', 'Sophie', 'Arthur']), @name.group_concat(',', [@score.asc, @name.asc]))
204
- assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: ['Lucas', 'Sophie', 'Arthur']), @name.group_concat(',', @score.asc, @name.asc))
205
- assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: ['Lucas', 'Sophie', 'Arthur']), @name.group_concat(',', order: [@score.asc, @name.asc]))
246
+ assert_equal 'Arthur,Lucas,Sophie', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', @name.asc))
247
+ assert_equal 'Sophie,Lucas,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', @name.desc))
248
+ assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', [@score.asc, @name.asc]))
249
+ assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', @score.asc, @name.asc))
250
+ assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', order: [@score.asc, @name.asc]))
206
251
  end
207
252
 
208
253
  def test_length
@@ -294,16 +339,16 @@ module ArelExtensions
294
339
  skip "Sqlite version can't load extension for regexp" if $sqlite && $load_extension_disabled
295
340
  skip 'SQL Server does not know about REGEXP without extensions' if @env_db == 'mssql'
296
341
  assert_equal 1, User.where(@name =~ '^M').count
297
- assert_equal 7, User.where(@name !~ '^L').count
342
+ assert_equal 8, User.where(@name !~ '^L').count
298
343
  assert_equal 1, User.where(@name =~ /^M/).count
299
- assert_equal 7, User.where(@name !~ /^L/).count
344
+ assert_equal 8, User.where(@name !~ /^L/).count
300
345
  end
301
346
 
302
347
  def test_imatches
303
348
  # puts User.where(@name.imatches('m%')).to_sql
304
349
  assert_equal 1, User.where(@name.imatches('m%')).count
305
350
  assert_equal 4, User.where(@name.imatches_any(['L%', '%e'])).count
306
- assert_equal 7, User.where(@name.idoes_not_match('L%')).count
351
+ assert_equal 8, User.where(@name.idoes_not_match('L%')).count
307
352
  end
308
353
 
309
354
  def test_replace
@@ -328,8 +373,8 @@ module ArelExtensions
328
373
  skip "Sqlite version can't load extension for soundex" if $sqlite && $load_extension_disabled
329
374
  skip "PostgreSql version can't load extension for soundex" if @env_db == 'postgresql'
330
375
  assert_equal 'C540', t(@camille, @name.soundex)
331
- assert_equal 9, User.where(@name.soundex.eq(@name.soundex)).count
332
- assert_equal 9, User.where(@name.soundex == @name.soundex).count
376
+ assert_equal 10, User.where(@name.soundex.eq(@name.soundex)).count
377
+ assert_equal 10, User.where(@name.soundex == @name.soundex).count
333
378
  end
334
379
 
335
380
  def test_change_case
@@ -374,6 +419,23 @@ module ArelExtensions
374
419
  assert_equal 'true', t(@neg, @comments.not_blank.then('true', 'false'))
375
420
  end
376
421
 
422
+ # This test repeats a lot of `test_blank` cases.
423
+ def test_present
424
+ if @env_db == 'postgresql'
425
+ assert_includes [true, 't'], t(@myung, @name.present) # depends of adapter
426
+ assert_includes [false, 'f'], t(@myung, @comments.present)
427
+ end
428
+ assert_equal 1, @myung.where(@name.present).count
429
+ assert_equal 0, @myung.where(@comments.present).count
430
+ assert_equal 0, @sophie.where(@comments.present).count
431
+ assert_equal 0, @camille.where(@comments.present).count
432
+
433
+ assert_equal 1, @neg.where(@comments.present).count
434
+ assert_equal 'true', t(@myung, @name.present.then('true', 'false'))
435
+ assert_equal 'false', t(@myung, @comments.present.then('true', 'false'))
436
+ assert_equal 'true', t(@neg, @comments.present.then('true', 'false'))
437
+ end
438
+
377
439
  def test_format
378
440
  assert_equal '2016-05-23', t(@lucas, @created_at.format('%Y-%m-%d'))
379
441
  assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S'))
@@ -419,27 +481,32 @@ module ArelExtensions
419
481
  }
420
482
  }
421
483
 
422
- skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if !['mssql', 'mysql', 'oracle', 'postgresql'].include?(ENV['DB'])
484
+ skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if !%w[mssql mysql oracle postgresql].include?(ENV['DB'])
485
+ # TODO: Standarize timezone conversion across all databases.
486
+ # This test case will be refactored and should work the same across all vendors.
487
+ if ENV['DB'] == 'mssql' && /Microsoft SQL Server (\d+)/.match(ActiveRecord::Base.connection.select_value('SELECT @@version'))[1].to_i < 2016
488
+ skip "SQL Server < 2016 is not currently supported"
489
+ end
423
490
 
424
491
  tz = ENV['DB'] == 'mssql' ? time_zones['mssql'] : time_zones['posix']
425
492
 
426
493
  assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['utc']))
427
- assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', { tz['utc'] => tz['sao_paulo'] }))
428
- assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', { tz['utc'] => tz['tahiti'] }))
494
+ assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['sao_paulo']}))
495
+ assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['tahiti']}))
429
496
 
430
497
  # Skipping conversion from UTC to the desired timezones fails in SQL
431
498
  # Server and Postgres. This is mainly due to the fact that timezone
432
499
  # information is not preserved in the column itself.
433
500
  #
434
501
  # MySQL is happy to consider that times by default are in UTC.
435
- assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', { tz['utc'] => tz['paris'] }))
502
+ assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
436
503
  refute_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['paris'])) if !['mysql'].include?(ENV['DB'])
437
504
 
438
505
  # Winter/Summer time
439
- assert_equal '2014/08/03 14:42:00', t(@lucas, (@updated_at + 5.months).format('%Y/%m/%d %H:%M:%S', { tz['utc'] => tz['paris'] }))
506
+ assert_equal '2014/08/03 14:42:00', t(@lucas, (@updated_at + 5.months).format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
440
507
  if ENV['DB'] == 'mssql'
441
- assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', { tz['utc'] => tz['paris'] }))
442
- assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', { tz['utc'] => tz['paris'] }))
508
+ assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
509
+ assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
443
510
  else
444
511
  assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
445
512
  assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
@@ -463,7 +530,7 @@ module ArelExtensions
463
530
  end
464
531
 
465
532
  def test_format_iso_year_of_week
466
- skip "Unsupported ISO year of week for DB=#{ENV['DB']}" if ['mssql', 'sqlite'].include?(ENV['DB'])
533
+ skip "Unsupported ISO year of week for DB=#{ENV['DB']}" if %w[mssql sqlite].include?(ENV['DB'])
467
534
  assert_equal '2014', t(@lucas, @updated_at.format('%G'))
468
535
 
469
536
  {
@@ -480,7 +547,7 @@ module ArelExtensions
480
547
  end
481
548
 
482
549
  def test_format_date_with_names
483
- skip "#{ENV['DB']} does not support a variety of word-based formatting for month and day names" if ['mssql'].include?(ENV['DB'])
550
+ skip "#{ENV['DB']} does not support a variety of word-based formatting for month and day names" if %w[mssql sqlite].include?(ENV['DB'])
484
551
  assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
485
552
  assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
486
553
 
@@ -491,9 +558,9 @@ module ArelExtensions
491
558
 
492
559
  def switch_to_lang(lang)
493
560
  languages = {
494
- 'mssql' => { :en => 'English', :fr => 'French' },
495
- 'mysql' => { :en => 'en_US', :fr => 'fr_FR' },
496
- 'postgresql' => { :en => 'en_US.utf8', :fr => 'fr_FR.utf8' }
561
+ 'mssql' => {en: 'English', fr: 'French'},
562
+ 'mysql' => {en: 'en_US', fr: 'fr_FR'},
563
+ 'postgresql' => {en: 'en_US.utf8', fr: 'fr_FR.utf8'}
497
564
  }
498
565
 
499
566
  sql = {
@@ -513,27 +580,29 @@ module ArelExtensions
513
580
  #
514
581
  # Tests should assert one single thing in principle, but until we
515
582
  # refactor this whole thing, we'll have to do tricks of this sort.
516
- switch_to_lang(:en)
517
- case ENV['DB']
518
- when 'mysql', 'postgresql'
519
- assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
520
- assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
521
- when 'mssql'
522
- assert_equal 'Monday, 03 March 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
523
- end
524
- switch_to_lang(:fr)
525
- case ENV['DB']
526
- when 'mysql'
527
- assert_equal 'lun, 03 mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
528
- assert_equal 'lundi, 03 mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
529
- when 'postgresql'
530
- assert_equal 'Lun., 03 Mars 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
531
- assert_equal 'Lundi, 03 Mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
532
- when 'mssql'
533
- assert_equal 'lundi, 03 mars 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
583
+ begin
584
+ switch_to_lang(:en)
585
+ case ENV['DB']
586
+ when 'mysql', 'postgresql'
587
+ assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
588
+ assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
589
+ when 'mssql'
590
+ assert_equal 'Monday, 03 March 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
591
+ end
592
+ switch_to_lang(:fr)
593
+ case ENV['DB']
594
+ when 'mysql'
595
+ assert_equal 'lun, 03 mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
596
+ assert_equal 'lundi, 03 mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
597
+ when 'postgresql'
598
+ assert_equal 'Lun., 03 Mars 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
599
+ assert_equal 'Lundi, 03 Mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
600
+ when 'mssql'
601
+ assert_equal 'lundi, 03 mars 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
602
+ end
603
+ ensure
604
+ switch_to_lang(:en)
534
605
  end
535
- ensure
536
- switch_to_lang(:en)
537
606
  end
538
607
 
539
608
  def test_coalesce
@@ -558,6 +627,24 @@ module ArelExtensions
558
627
  assert_equal 'Laure10', t(@laure, @comments.coalesce('Laure') + 10)
559
628
  end
560
629
 
630
+ def test_coalesce_blank
631
+ assert_equal 'Myung', t(@myung, @comments.coalesce_blank('Myung').coalesce_blank('ignored'))
632
+ assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ').coalesce_blank('Myung'))
633
+ assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ', 'Myung'))
634
+ assert_equal '2016-05-23', t(@myung, @created_at.coalesce_blank(Date.new(2022, 1, 1)).format('%Y-%m-%d'))
635
+ assert_equal 'Laure', t(@laure, @comments.coalesce_blank('Laure'))
636
+ assert_equal 100, t(@test, @age.coalesce_blank(100))
637
+ assert_equal 20, t(@test, @age.coalesce_blank(20))
638
+ assert_equal 20, t(@test, @age.coalesce_blank(10) + 10)
639
+ assert_equal 'Laure10', t(@laure, @comments.coalesce_blank('Laure') + 10)
640
+
641
+ skip 'mssql does not support null in case results' if @env_db == 'mssql'
642
+
643
+ assert_equal 'Camille concat', t(@camille, @name.coalesce_blank(Arel.null, 'default') + ' concat')
644
+ assert_equal 'Myung', t(@myung, @comments.coalesce_blank(Arel.null, 'Myung'))
645
+ assert_equal 'Camille', t(@camille, @name.coalesce_blank(Arel.null, 'default'))
646
+ end
647
+
561
648
  # Comparators
562
649
  def test_number_comparator
563
650
  assert_equal 2, User.where(@age < 6).count
@@ -570,7 +657,7 @@ module ArelExtensions
570
657
  def test_date_comparator
571
658
  d = Date.new(2016, 5, 23)
572
659
  assert_equal 0, User.where(@created_at < d).count
573
- assert_equal 9, User.where(@created_at >= d).count
660
+ assert_equal 10, User.where(@created_at >= d).count
574
661
  end
575
662
 
576
663
  def test_date_duration
@@ -602,8 +689,8 @@ module ArelExtensions
602
689
  def test_datetime_diff
603
690
  assert_equal 0, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 42)).to_i
604
691
  if @env_db == 'oracle' && Arel::VERSION.to_i > 6 # in rails 5, result is multiplied by 24*60*60 = 86400...
605
- assert_equal 42 * 86400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
606
- assert_equal(-3600 * 86400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
692
+ assert_equal 42 * 86_400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
693
+ assert_equal(-3600 * 86_400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
607
694
  else
608
695
  assert_equal 42, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
609
696
  assert_equal(-3600, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
@@ -658,12 +745,12 @@ module ArelExtensions
658
745
  # TODO; cast types
659
746
  def test_cast_types
660
747
  assert_equal '5', t(@lucas, @age.cast(:string))
661
- skip 'jdbc adapters does not work properly here (v52 works fine)' if RUBY_PLATFORM =~ /java/i
748
+ skip 'jdbc adapters does not work properly here (v52 works fine)' if RUBY_PLATFORM.match?(/java/i)
662
749
  if @env_db == 'mysql' || @env_db == 'postgresql' || @env_db == 'oracle' || @env_db == 'mssql'
663
750
  assert_equal 1, t(@laure, Arel.when(@duration.cast(:time).cast(:string).eq('12:42:21')).then(1).else(0)) unless @env_db == 'oracle' || @env_db == 'mssql'
664
751
  assert_equal 1, t(@laure, Arel.when(@duration.cast(:time).eq('12:42:21')).then(1).else(0)) unless @env_db == 'oracle'
665
- assert_equal '20.16', t(@laure, @score.cast(:string)).gsub(/[0]*\z/, '')
666
- assert_equal '20.161', t(@laure, @score.cast(:string) + 1).gsub(/[0]*1\z/, '1')
752
+ assert_equal '20.16', t(@laure, @score.cast(:string)).gsub(/0*\z/, '')
753
+ assert_equal '20.161', t(@laure, @score.cast(:string) + 1).gsub(/0*1\z/, '1')
667
754
  assert_equal 21.16, t(@laure, @score.cast(:string).cast(:decimal) + 1)
668
755
  assert_equal 21, t(@laure, @score.cast(:string).cast(:int) + 1)
669
756
 
@@ -683,6 +770,26 @@ module ArelExtensions
683
770
  end
684
771
  end
685
772
 
773
+ def test_if_present
774
+ assert_nil t(@myung, @comments.if_present)
775
+ assert_equal 0, t(@myung, @comments.if_present.count)
776
+ assert_equal 20.16, t(@myung, @score.if_present)
777
+ assert_equal '2016-05-23', t(@myung, @created_at.if_present.format('%Y-%m-%d'))
778
+ assert_nil t(@laure, @comments.if_present)
779
+
780
+ assert_nil t(@nilly, @duration.if_present.format('%Y-%m-%d'))
781
+
782
+ # NOTE: here we're testing the capacity to format a nil value,
783
+ # however, @comments is a text field, and not a date/datetime field,
784
+ # so Postgres will rightfully complain when we format the text:
785
+ # we need to cast it first.
786
+ if @env_db == 'postgresql'
787
+ assert_nil t(@laure, @comments.cast(:date).if_present.format('%Y-%m-%d'))
788
+ else
789
+ assert_nil t(@laure, @comments.if_present.format('%Y-%m-%d'))
790
+ end
791
+ end
792
+
686
793
  def test_is_null
687
794
  # puts User.where(@age.is_null).select(@name).to_sql
688
795
  # puts @age.is_null
@@ -718,7 +825,7 @@ module ArelExtensions
718
825
  def test_math_minus
719
826
  d = Date.new(2016, 5, 20)
720
827
  # Datediff
721
- assert_equal 9, User.where((@created_at - @created_at).eq(0)).count
828
+ assert_equal 10, User.where((@created_at - @created_at).eq(0)).count
722
829
  assert_equal 3, @laure.select((@created_at - d).as('res')).first.res.abs.to_i
723
830
  # Substraction
724
831
  assert_equal 0, User.where((@age - 10).eq(50)).count
@@ -747,8 +854,8 @@ module ArelExtensions
747
854
  assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)) + @ut.project(@age).where(@age.eq(23)) + @ut.project(@age).where(@age.eq(21))).as('my_union')).length
748
855
  assert_equal 2, User.select('*').from((@ut.project(@age).where(@age.eq(20)) + @ut.project(@age).where(@age.eq(20)) + @ut.project(@age).where(@age.eq(21))).as('my_union')).length
749
856
 
750
- assert_equal 3, User.find_by_sql((@ut.project(@age).where(@age.gt(22)).union_all(@ut.project(@age).where(@age.lt(0)))).to_sql).length
751
- assert_equal 3, User.find_by_sql((@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(20))).union_all(@ut.project(@age).where(@age.eq(21)))).to_sql).length
857
+ assert_equal 3, User.find_by_sql(@ut.project(@age).where(@age.gt(22)).union_all(@ut.project(@age).where(@age.lt(0))).to_sql).length
858
+ assert_equal 3, User.find_by_sql(@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(20))).union_all(@ut.project(@age).where(@age.eq(21))).to_sql).length
752
859
  assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.gt(22)).union_all(@ut.project(@age).where(@age.lt(0)))).as('my_union')).length
753
860
  assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(23))).union_all(@ut.project(@age).where(@age.eq(21)))).as('my_union')).length
754
861
  assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(20))).union_all(@ut.project(@age).where(@age.eq(21)))).as('my_union')).length
@@ -786,10 +893,10 @@ module ArelExtensions
786
893
  assert_includes ['$ 6,56e1 €', '$ 6,56e+01 €'], t(@arthur, @score.format_number('$ %.2e €', 'fr_FR'))
787
894
  assert_includes ['$ 6,56E1 €', '$ 6,56E+01 €'], t(@arthur, @score.format_number('$ %.2E €', 'fr_FR'))
788
895
  assert_includes ['$ 6,562E1 €', '$ 6,562E+01 €'], t(@arthur, @score.format_number('$ %.3E €', 'fr_FR'))
789
- assert_equal '123 456 765,6', t(@arthur, (@score + 123456700).format_number('%.1f', 'sv_SE')).gsub("\u00A0", ' ') # some DBMS put no-break space here (it makes sense thus)
790
- assert_equal '123456765,6', t(@arthur, (@score + 123456700).format_number('%.1f', 'fr_FR')).gsub("\u00A0", '') # because SqlServer does it like no one else
791
- assert_equal '123,456,765.6', t(@arthur, (@score + 123456700).format_number('%.1f', 'en_US'))
792
- assert_equal ' 123,456,765.6', t(@arthur, (@score + 123456700).format_number('%16.1f', 'en_US'))
896
+ assert_equal '123 456 765,6', t(@arthur, (@score + 123_456_700).format_number('%.1f', 'sv_SE')).tr("\u00A0", ' ') # some DBMS put no-break space here (it makes sense thus)
897
+ assert_equal '123456765,6', t(@arthur, (@score + 123_456_700).format_number('%.1f', 'fr_FR')).delete("\u00A0") # because SqlServer does it like no one else
898
+ assert_equal '123,456,765.6', t(@arthur, (@score + 123_456_700).format_number('%.1f', 'en_US'))
899
+ assert_equal ' 123,456,765.6', t(@arthur, (@score + 123_456_700).format_number('%16.1f', 'en_US'))
793
900
  assert_equal '$ 0,00 €', t(@arthur, @score.when(65.62).then(Arel.sql('null')).else(1).format_number('$ %.2f €', 'fr_FR'))
794
901
  assert_equal '$ 0,00 €', t(@arthur, (@score - 65.62).format_number('$ %.2f €', 'fr_FR'))
795
902
  end
@@ -811,7 +918,7 @@ module ArelExtensions
811
918
  assert_equal '1', t(@arthur, Arel.when(@comments.ai_matches('arrete')).then('1').else('0'))
812
919
  assert_equal '1', t(@arthur, Arel.when(@comments.ai_matches('àrrétè')).then('1').else('0'))
813
920
  assert_equal '0', t(@arthur, Arel.when(@comments.ai_matches('arretez')).then('1').else('0'))
814
- if !['oracle', 'postgresql', 'mysql'].include?(@env_db) # AI => CI
921
+ if !%w[oracle postgresql mysql].include?(@env_db) # AI => CI
815
922
  assert_equal '0', t(@arthur, Arel.when(@comments.ai_matches('Arrete')).then('1').else('0'))
816
923
  assert_equal '0', t(@arthur, Arel.when(@comments.ai_matches('Arrêté')).then('1').else('0'))
817
924
  end
@@ -838,8 +945,8 @@ module ArelExtensions
838
945
 
839
946
  def test_subquery_with_order
840
947
  skip if ['mssql'].include?(@env_db) && Arel::VERSION.to_i < 10
841
- assert_equal 9, User.where(name: User.select(:name).order(:name)).count
842
- assert_equal 9, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
948
+ assert_equal 10, User.where(name: User.select(:name).order(:name)).count
949
+ assert_equal 10, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
843
950
  if !['mysql'].include?(@env_db) # MySql can't have limit in IN subquery
844
951
  assert_equal 2, User.where(name: User.select(:name).order(:name).limit(2)).count
845
952
  # assert_equal 6, User.where(name: User.select(:name).order(:name).offset(2)).count
@@ -915,7 +1022,7 @@ module ArelExtensions
915
1022
  end
916
1023
 
917
1024
  def test_alias_shortened
918
- if ['postgresql', 'oracle'].include?(@env_db)
1025
+ if %w[postgresql oracle].include?(@env_db)
919
1026
  new_alias = Arel.shorten('azerty' * 15)
920
1027
  at = User.arel_table.alias('azerty' * 15)
921
1028
  assert_equal "\"user_tests\" \"#{new_alias}\"".downcase, User.arel_table.alias('azerty' * 15).to_sql.downcase
@@ -956,23 +1063,23 @@ module ArelExtensions
956
1063
  skip "Can't be tested on travis"
957
1064
  # creation
958
1065
  assert_equal 'Arthur', t(@arthur, Arel.json(@name))
959
- assert_equal ['Arthur', 'Arthur'], parse_json(t(@arthur, Arel.json(@name, @name)))
1066
+ assert_equal %w[Arthur Arthur], parse_json(t(@arthur, Arel.json(@name, @name)))
960
1067
  assert_equal ({'Arthur' => 'Arthur', 'Arthur2' => 'ArthurArthur'}), parse_json(t(@arthur, Arel.json({@name => @name, @name + '2' => @name + @name})))
961
1068
  assert_equal ({'Arthur' => 'Arthur', 'Arthur2' => 1}), parse_json(t(@arthur, Arel.json({@name => @name, @name + '2' => 1})))
962
- assert_equal ([{'age' => 21}, {'name' => 'Arthur', 'score' => 65.62}]), parse_json(t(@arthur, Arel.json([{age: @age}, {name: @name, score: @score}])))
1069
+ assert_equal [{'age' => 21}, {'name' => 'Arthur', 'score' => 65.62}], parse_json(t(@arthur, Arel.json([{age: @age}, {name: @name, score: @score}])))
963
1070
 
964
1071
  # aggregate
965
1072
  assert_equal ({'5' => 'Lucas', '15' => 'Sophie', '23' => 'Myung', '25' => 'Laure'}),
966
1073
  parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16), Arel.json({@age => @name}).group(false)))
967
1074
  assert_equal ({'5' => 'Lucas', '15' => 'Sophie', '23' => 'Myung', '25' => 'Laure', 'Laure' => 25, 'Lucas' => 5, 'Myung' => 23, 'Sophie' => 15}),
968
1075
  parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16), Arel.json({@age => @name, @name => @age}).group(false)))
969
- assert_equal ([{'5' => 'Lucas'}, { '15' => 'Sophie'}, { '23' => 'Myung'}, { '25' => 'Laure'}]),
1076
+ assert_equal [{'5' => 'Lucas'}, {'15' => 'Sophie'}, {'23' => 'Myung'}, {'25' => 'Laure'}],
970
1077
  parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score), Arel.json({@age => @name}).group(true, [@age])))
971
1078
 
972
1079
  # puts User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score, Arel.json({@age => @name}).group(true,[@age])).to_sql
973
1080
  # puts User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score, Arel.json({@age => @name}).group(true,[@age])).to_a
974
1081
 
975
- skip 'Not Yet Implemented' if $sqlite || ['oracle', 'mssql'].include?(@env_db)
1082
+ skip 'Not Yet Implemented' if $sqlite || %w[oracle mssql].include?(@env_db)
976
1083
  # get
977
1084
  h1 = Arel.json({@name => @name + @name, @name + '2' => 1})
978
1085
  assert_equal 'ArthurArthur', parse_json(t(@arthur, h1.get(@name)))
@@ -981,13 +1088,13 @@ module ArelExtensions
981
1088
  assert_equal 21, parse_json(t(@arthur, h2.get(0).get('age')))
982
1089
  assert_nil t(@arthur, h2.get('age'))
983
1090
  # set
984
- assert_equal ({'Arthur' => ['toto', 'tata'], 'Arthur2' => 1}), parse_json(t(@arthur, h1.set(@name, ['toto', 'tata'])))
1091
+ assert_equal ({'Arthur' => %w[toto tata], 'Arthur2' => 1}), parse_json(t(@arthur, h1.set(@name, %w[toto tata])))
985
1092
  assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.set(@name + '3', 2)))
986
1093
  assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1, 'Arthur3' => nil}), parse_json(t(@arthur, h1.set(@name + '3', nil)))
987
1094
  assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1, 'Arthur3' => {'a' => 2}}), parse_json(t(@arthur, h1.set(@name + '3', {a: 2})))
988
1095
  # merge
989
- assert_equal ({'Arthur' => ['toto', 'tata'], 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.merge({@name => ['toto', 'tata']}, {@name + '3' => 2})))
990
- assert_equal ({'Arthur' => ['toto', 'tata'], 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.merge({@name => ['toto', 'tata'], @name + '3' => 2})))
1096
+ assert_equal ({'Arthur' => %w[toto tata], 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.merge({@name => %w[toto tata]}, {@name + '3' => 2})))
1097
+ assert_equal ({'Arthur' => %w[toto tata], 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.merge({@name => %w[toto tata], @name + '3' => 2})))
991
1098
  assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1}), parse_json(t(@arthur, h1.merge({})))
992
1099
  end
993
1100
 
@@ -58,15 +58,15 @@ END;])
58
58
  connect_db
59
59
  setup_db
60
60
  @table = Arel::Table.new(:user_tests)
61
- @cols = ['id', 'name', 'comments', 'created_at']
61
+ @cols = %w[id name comments created_at]
62
62
  @data = [
63
63
  [23, 'nom1', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor.', '2016-01-01'],
64
64
  [25, 'nom2', 'sdfdsfdsfsdf', '2016-01-02']
65
65
  ]
66
- @cols2 = ['name', 'comments', 'created_at']
66
+ @cols2 = %w[name comments created_at]
67
67
  @data2 = [
68
68
  ['nom3', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor.', '2016-01-01'],
69
- ['nom4', 'sdfdsfdsfsdf', '2016-01-04']
69
+ %w[nom4 sdfdsfdsfsdf 2016-01-04]
70
70
  ]
71
71
  end
72
72
 
@@ -27,7 +27,7 @@ module ArelExtensions
27
27
  t.column :price, :decimal
28
28
  end
29
29
  @table = Arel::Table.new(:users)
30
- @cols = ['id', 'name', 'comments', 'created_at']
30
+ @cols = %w[id name comments created_at]
31
31
  @data = [
32
32
  [23, 'nom1', 'sdfdsfdsfsdf', '2016-01-01'],
33
33
  [25, 'nom2', 'sdfdsfdsfsdf', '2016-01-01']
data/version_v1.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = '1.3.4'.freeze
2
+ VERSION = '1.3.6'.freeze
3
3
  end
data/version_v2.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = '2.1.4'.freeze
2
+ VERSION = '2.1.6'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arel_extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.4
4
+ version: 2.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yann Azoury
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-03-24 00:00:00.000000000 Z
13
+ date: 2022-11-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -40,20 +40,6 @@ dependencies:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
42
  version: '5.9'
43
- - !ruby/object:Gem::Dependency
44
- name: rdoc
45
- requirement: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 6.3.1
50
- type: :development
51
- prerelease: false
52
- version_requirements: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: 6.3.1
57
43
  - !ruby/object:Gem::Dependency
58
44
  name: rake
59
45
  requirement: !ruby/object:Gem::Requirement
@@ -86,15 +72,17 @@ files:
86
72
  - ".rubocop.yml"
87
73
  - Gemfile
88
74
  - MIT-LICENSE.txt
75
+ - NEWS.md
89
76
  - README.md
90
77
  - Rakefile
91
78
  - SQL_Challenges.md
92
79
  - TODO
80
+ - appveyor.yml
93
81
  - arel_extensions.gemspec
94
82
  - functions.html
95
83
  - gemfiles/rails3.gemfile
96
- - gemfiles/rails4.gemfile
97
- - gemfiles/rails5_0.gemfile
84
+ - gemfiles/rails4_2.gemfile
85
+ - gemfiles/rails5.gemfile
98
86
  - gemfiles/rails5_1_4.gemfile
99
87
  - gemfiles/rails5_2.gemfile
100
88
  - gemfiles/rails6.gemfile
@@ -149,7 +137,9 @@ files:
149
137
  - lib/arel_extensions/nodes/rand.rb
150
138
  - lib/arel_extensions/nodes/repeat.rb
151
139
  - lib/arel_extensions/nodes/replace.rb
140
+ - lib/arel_extensions/nodes/rollup.rb
152
141
  - lib/arel_extensions/nodes/round.rb
142
+ - lib/arel_extensions/nodes/select.rb
153
143
  - lib/arel_extensions/nodes/soundex.rb
154
144
  - lib/arel_extensions/nodes/std.rb
155
145
  - lib/arel_extensions/nodes/substring.rb
@@ -1,29 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gem 'arel', '~> 6.0'
4
-
5
- group :development, :test do
6
- gem 'activesupport', '~> 4.0'
7
- gem 'activemodel', '~> 4.0'
8
- gem 'activerecord', '~> 4.0'
9
-
10
- gem 'sqlite3', '<= 1.3.13', platforms: [:mri, :mswin, :mingw]
11
- gem 'mysql2', '0.4.10', platforms: [:mri, :mswin, :mingw]
12
- gem 'pg', '< 1.0.0', platforms: [:mri, :mingw]
13
-
14
- gem 'tiny_tds', platforms: [:mri, :mingw, :mswin] if RUBY_PLATFORM =~ /windows/
15
- gem 'activerecord-sqlserver-adapter', '~> 4.2.0', platforms: [:mri, :mingw, :mswin] if RUBY_PLATFORM =~ /windows/
16
-
17
- gem 'ruby-oci8', platforms: [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
18
- gem 'activerecord-oracle_enhanced-adapter', '~> 1.6.0' if ENV.has_key? 'ORACLE_HOME'
19
-
20
- # for JRuby
21
- gem 'activerecord-jdbc-adapter', '~> 1.3', platforms: :jruby
22
- gem 'jdbc-sqlite3', platforms: :jruby
23
- gem 'activerecord-jdbcsqlite3-adapter', platforms: :jruby
24
- gem 'activerecord-jdbcmysql-adapter', platforms: :jruby
25
- gem 'activerecord-jdbcpostgresql-adapter', platforms: :jruby
26
- gem 'activerecord-jdbcmssql-adapter', platforms: :jruby
27
- end
28
-
29
- gemspec path: '../'