arel_extensions 2.1.5 → 2.1.7

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.
@@ -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)
@@ -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,124 +419,152 @@ module ArelExtensions
374
419
  assert_equal 'true', t(@neg, @comments.not_blank.then('true', 'false'))
375
420
  end
376
421
 
377
- def test_format
378
- assert_equal '2016-05-23', t(@lucas, @created_at.format('%Y-%m-%d'))
379
- assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S'))
380
- assert_equal '12:42%', t(@lucas, @updated_at.format('%R%%'))
381
-
382
- # The following tests will ensure proper conversion of timestamps to
383
- # requested timezones.
384
- #
385
- # The names of the timezones is highly dependant on the underlying
386
- # operating system, and this is why we need to handle each database
387
- # separately: the images we're using to test these databases are
388
- # different. So don't rely on the provided examples. Your setup is your
389
- # reference.
390
- #
391
- # One could always have portable code if s/he uses standard
392
- # abbreviations, like:
393
- #
394
- # 1. CET => Central European Time
395
- # 2. CEST => Central European Summer Time
396
- #
397
- # Which implies that the caller should handle daylight saving detection.
398
- # In fact, CET will handle daylight saving in MySQL but not Postgres.
399
- #
400
- # It looks like the posix convention is supported by mysql and
401
- # postgresql, e.g.:
402
- #
403
- # posix/Europe/Paris
404
- # posix/America/Nipigon
405
- #
406
- # so it looks like a more reliably portable way of specifying it.
407
- time_zones = {
408
- 'mssql' => {
409
- 'utc' => 'UTC',
410
- 'sao_paulo' => 'Argentina Standard Time',
411
- 'tahiti' => 'Hawaiian Standard Time',
412
- 'paris' => 'Central European Standard Time'
413
- },
414
- 'posix' => {
415
- 'utc' => 'UTC',
416
- 'sao_paulo' => 'America/Sao_Paulo',
417
- 'tahiti' => 'Pacific/Tahiti',
418
- 'paris' => 'Europe/Paris'
419
- }
420
- }
421
-
422
- skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if !%w[mssql mysql oracle postgresql].include?(ENV['DB'])
423
- # TODO: Standarize timezone conversion across all databases.
424
- # This test case will be refactored and should work the same across all vendors.
425
- if ENV['DB'] == 'mssql' && /Microsoft SQL Server (\d+)/.match(ActiveRecord::Base.connection.select_value('SELECT @@version'))[1].to_i < 2016
426
- skip "SQL Server < 2016 is not currently supported"
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
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
428
432
 
429
- tz = ENV['DB'] == 'mssql' ? time_zones['mssql'] : time_zones['posix']
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
430
438
 
431
- assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['utc']))
432
- assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['sao_paulo']}))
433
- assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['tahiti']}))
439
+ def test_format
440
+ %i[format format_date].each do |method|
441
+ assert_equal '2016-05-23', t(@lucas, @created_at.send(method, '%Y-%m-%d'))
442
+ assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S'))
443
+ assert_equal '12:42%', t(@lucas, @updated_at.send(method, '%R%%'))
444
+
445
+ # The following tests will ensure proper conversion of timestamps to
446
+ # requested timezones.
447
+ #
448
+ # The names of the timezones is highly dependant on the underlying
449
+ # operating system, and this is why we need to handle each database
450
+ # separately: the images we're using to test these databases are
451
+ # different. So don't rely on the provided examples. Your setup is your
452
+ # reference.
453
+ #
454
+ # One could always have portable code if s/he uses standard
455
+ # abbreviations, like:
456
+ #
457
+ # 1. CET => Central European Time
458
+ # 2. CEST => Central European Summer Time
459
+ #
460
+ # Which implies that the caller should handle daylight saving detection.
461
+ # In fact, CET will handle daylight saving in MySQL but not Postgres.
462
+ #
463
+ # It looks like the posix convention is supported by mysql and
464
+ # postgresql, e.g.:
465
+ #
466
+ # posix/Europe/Paris
467
+ # posix/America/Nipigon
468
+ #
469
+ # so it looks like a more reliably portable way of specifying it.
470
+ time_zones = {
471
+ 'mssql' => {
472
+ 'utc' => 'UTC',
473
+ 'sao_paulo' => 'Argentina Standard Time',
474
+ 'tahiti' => 'Hawaiian Standard Time',
475
+ 'paris' => 'Central European Standard Time'
476
+ },
477
+ 'posix' => {
478
+ 'utc' => 'UTC',
479
+ 'sao_paulo' => 'America/Sao_Paulo',
480
+ 'tahiti' => 'Pacific/Tahiti',
481
+ 'paris' => 'Europe/Paris'
482
+ }
483
+ }
484
+
485
+ skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if !%w[mssql mysql oracle postgresql].include?(ENV['DB'])
486
+ # TODO: Standarize timezone conversion across all databases.
487
+ # This test case will be refactored and should work the same across all vendors.
488
+ if ENV['DB'] == 'mssql' && /Microsoft SQL Server (\d+)/.match(ActiveRecord::Base.connection.select_value('SELECT @@version'))[1].to_i < 2016
489
+ skip "SQL Server < 2016 is not currently supported"
490
+ end
434
491
 
435
- # Skipping conversion from UTC to the desired timezones fails in SQL
436
- # Server and Postgres. This is mainly due to the fact that timezone
437
- # information is not preserved in the column itself.
438
- #
439
- # MySQL is happy to consider that times by default are in UTC.
440
- assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
441
- 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'])
442
-
443
- # Winter/Summer time
444
- 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']}))
445
- if ENV['DB'] == 'mssql'
446
- 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']}))
447
- 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']}))
448
- else
449
- 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']))
450
- 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']))
492
+ tz = ENV['DB'] == 'mssql' ? time_zones['mssql'] : time_zones['posix']
493
+
494
+ assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', tz['utc']))
495
+ assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['sao_paulo']}))
496
+ assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['tahiti']}))
497
+
498
+ # Skipping conversion from UTC to the desired timezones fails in SQL
499
+ # Server and Postgres. This is mainly due to the fact that timezone
500
+ # information is not preserved in the column itself.
501
+ #
502
+ # MySQL is happy to consider that times by default are in UTC.
503
+ assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
504
+ refute_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', tz['paris'])) if !['mysql'].include?(ENV['DB'])
505
+
506
+ # Winter/Summer time
507
+ assert_equal '2014/08/03 14:42:00', t(@lucas, (@updated_at + 5.months).send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
508
+ if ENV['DB'] == 'mssql'
509
+ assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
510
+ assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
511
+ else
512
+ assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', tz['paris']))
513
+ assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', tz['paris']))
514
+ end
451
515
  end
452
516
  end
453
517
 
454
518
  def test_format_iso_week
455
- skip "Unsupported ISO week number for DB=#{ENV['DB']}" if ['sqlite'].include?(ENV['DB'])
456
- assert_equal '10', t(@lucas, @updated_at.format('%V'))
457
- {
458
- '2024-01-01 10:42:00' => '01', # Monday
459
- '2030-01-01 10:42:00' => '01', # Tuesday
460
- '2025-01-01 10:42:00' => '01', # Wednesday
461
- '2026-01-01 10:42:00' => '01', # Thursday
462
- '2027-01-01 10:42:00' => '53', # Friday
463
- '2028-01-01 10:42:00' => '52', # Saturday
464
- '2034-01-01 10:42:00' => '52', # Sunday
465
- }.each do |date, exp|
466
- assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).format('%V'))
519
+ %i[format format_date].each do |method|
520
+ skip "Unsupported ISO week number for DB=#{ENV['DB']}" if ['sqlite'].include?(ENV['DB'])
521
+ assert_equal '10', t(@lucas, @updated_at.send(method, '%V'))
522
+ {
523
+ '2024-01-01 10:42:00' => '01', # Monday
524
+ '2030-01-01 10:42:00' => '01', # Tuesday
525
+ '2025-01-01 10:42:00' => '01', # Wednesday
526
+ '2026-01-01 10:42:00' => '01', # Thursday
527
+ '2027-01-01 10:42:00' => '53', # Friday
528
+ '2028-01-01 10:42:00' => '52', # Saturday
529
+ '2034-01-01 10:42:00' => '52', # Sunday
530
+ }.each do |date, exp|
531
+ assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).send(method, '%V'))
532
+ end
467
533
  end
468
534
  end
469
535
 
470
536
  def test_format_iso_year_of_week
471
537
  skip "Unsupported ISO year of week for DB=#{ENV['DB']}" if %w[mssql sqlite].include?(ENV['DB'])
472
- assert_equal '2014', t(@lucas, @updated_at.format('%G'))
473
-
474
- {
475
- '2024-01-01 10:42:00' => '2024', # Monday
476
- '2030-01-01 10:42:00' => '2030', # Tuesday
477
- '2025-01-01 10:42:00' => '2025', # Wednesday
478
- '2026-01-01 10:42:00' => '2026', # Thursday
479
- '2027-01-01 10:42:00' => '2026', # Friday
480
- '2028-01-01 10:42:00' => '2027', # Saturday
481
- '2034-01-01 10:42:00' => '2033', # Sunday
482
- }.each do |date, exp|
483
- assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).format('%G'))
538
+ %i[format format_date].each do |method|
539
+ assert_equal '2014', t(@lucas, @updated_at.send(method, '%G'))
540
+
541
+ {
542
+ '2024-01-01 10:42:00' => '2024', # Monday
543
+ '2030-01-01 10:42:00' => '2030', # Tuesday
544
+ '2025-01-01 10:42:00' => '2025', # Wednesday
545
+ '2026-01-01 10:42:00' => '2026', # Thursday
546
+ '2027-01-01 10:42:00' => '2026', # Friday
547
+ '2028-01-01 10:42:00' => '2027', # Saturday
548
+ '2034-01-01 10:42:00' => '2033', # Sunday
549
+ }.each do |date, exp|
550
+ assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).send(method, '%G'))
551
+ end
484
552
  end
485
553
  end
486
554
 
487
555
  def test_format_date_with_names
488
556
  skip "#{ENV['DB']} does not support a variety of word-based formatting for month and day names" if %w[mssql sqlite].include?(ENV['DB'])
489
- assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
490
- assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
557
+ %i[format format_date].each do |method|
558
+ assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
559
+ assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
560
+ end
491
561
 
492
562
  skip "#{ENV['DB']} does not support ALLCAPS month and day names" if ['mysql'].include?(ENV['DB'])
493
- assert_equal 'Mon, 03 MAR 14', t(@lucas, @updated_at.format('%a, %d %^b %y'))
494
- assert_equal 'Monday, 03 MARCH 14', t(@lucas, @updated_at.format('%A, %d %^B %y'))
563
+ %i[format format_date].each do |method|
564
+
565
+ assert_equal 'Mon, 03 MAR 14', t(@lucas, @updated_at.send(method, '%a, %d %^b %y'))
566
+ assert_equal 'Monday, 03 MARCH 14', t(@lucas, @updated_at.send(method, '%A, %d %^B %y'))
567
+ end
495
568
  end
496
569
 
497
570
  def switch_to_lang(lang)
@@ -518,28 +591,30 @@ module ArelExtensions
518
591
  #
519
592
  # Tests should assert one single thing in principle, but until we
520
593
  # refactor this whole thing, we'll have to do tricks of this sort.
521
- begin
522
- switch_to_lang(:en)
523
- case ENV['DB']
524
- when 'mysql', 'postgresql'
525
- assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
526
- assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
527
- when 'mssql'
528
- assert_equal 'Monday, 03 March 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
594
+ %i[format format_date].each do |method|
595
+ begin
596
+ switch_to_lang(:en)
597
+ case ENV['DB']
598
+ when 'mysql', 'postgresql'
599
+ assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
600
+ assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
601
+ when 'mssql'
602
+ assert_equal 'Monday, 03 March 2014', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
603
+ end
604
+ switch_to_lang(:fr)
605
+ case ENV['DB']
606
+ when 'mysql'
607
+ assert_equal 'lun, 03 mar 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
608
+ assert_equal 'lundi, 03 mars 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
609
+ when 'postgresql'
610
+ assert_equal 'Lun., 03 Mars 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
611
+ assert_equal 'Lundi, 03 Mars 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
612
+ when 'mssql'
613
+ assert_equal 'lundi, 03 mars 2014', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
614
+ end
615
+ ensure
616
+ switch_to_lang(:en)
529
617
  end
530
- switch_to_lang(:fr)
531
- case ENV['DB']
532
- when 'mysql'
533
- assert_equal 'lun, 03 mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
534
- assert_equal 'lundi, 03 mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
535
- when 'postgresql'
536
- assert_equal 'Lun., 03 Mars 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
537
- assert_equal 'Lundi, 03 Mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
538
- when 'mssql'
539
- assert_equal 'lundi, 03 mars 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
540
- end
541
- ensure
542
- switch_to_lang(:en)
543
618
  end
544
619
  end
545
620
 
@@ -565,6 +640,25 @@ module ArelExtensions
565
640
  assert_equal 'Laure10', t(@laure, @comments.coalesce('Laure') + 10)
566
641
  end
567
642
 
643
+ def test_coalesce_blank
644
+ assert_equal 'Myung', t(@myung, @comments.coalesce_blank('Myung').coalesce_blank('ignored'))
645
+ assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ').coalesce_blank('Myung'))
646
+ assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ', 'Myung'))
647
+ assert_equal '2016-05-23', t(@myung, @created_at.coalesce_blank(Date.new(2022, 1, 1)).format('%Y-%m-%d'))
648
+ assert_equal '2016-05-23', t(@myung, @created_at.coalesce_blank(Date.new(2022, 1, 1)).format_date('%Y-%m-%d'))
649
+ assert_equal 'Laure', t(@laure, @comments.coalesce_blank('Laure'))
650
+ assert_equal 100, t(@test, @age.coalesce_blank(100))
651
+ assert_equal 20, t(@test, @age.coalesce_blank(20))
652
+ assert_equal 20, t(@test, @age.coalesce_blank(10) + 10)
653
+ assert_equal 'Laure10', t(@laure, @comments.coalesce_blank('Laure') + 10)
654
+
655
+ skip 'mssql does not support null in case results' if @env_db == 'mssql'
656
+
657
+ assert_equal 'Camille concat', t(@camille, @name.coalesce_blank(Arel.null, 'default') + ' concat')
658
+ assert_equal 'Myung', t(@myung, @comments.coalesce_blank(Arel.null, 'Myung'))
659
+ assert_equal 'Camille', t(@camille, @name.coalesce_blank(Arel.null, 'default'))
660
+ end
661
+
568
662
  # Comparators
569
663
  def test_number_comparator
570
664
  assert_equal 2, User.where(@age < 6).count
@@ -577,7 +671,7 @@ module ArelExtensions
577
671
  def test_date_comparator
578
672
  d = Date.new(2016, 5, 23)
579
673
  assert_equal 0, User.where(@created_at < d).count
580
- assert_equal 9, User.where(@created_at >= d).count
674
+ assert_equal 10, User.where(@created_at >= d).count
581
675
  end
582
676
 
583
677
  def test_date_duration
@@ -654,8 +748,10 @@ module ArelExtensions
654
748
  t(@lucas, (@updated_at + Arel.duration('mn', (@updated_at.hour * 60 + @updated_at.minute))))
655
749
 
656
750
  assert_includes ['2024-03-03'], t(@lucas, (@updated_at + durPos).format('%Y-%m-%d'))
751
+ assert_includes ['2024-03-03'], t(@lucas, (@updated_at + durPos).format_date('%Y-%m-%d'))
657
752
  # puts (@updated_at - durPos).to_sql
658
753
  assert_includes ['2004-03-03'], t(@lucas, (@updated_at - durPos).format('%Y-%m-%d'))
754
+ assert_includes ['2004-03-03'], t(@lucas, (@updated_at - durPos).format_date('%Y-%m-%d'))
659
755
 
660
756
 
661
757
  # we test with the ruby object or the string because some adapters don't return an object Date
@@ -690,6 +786,30 @@ module ArelExtensions
690
786
  end
691
787
  end
692
788
 
789
+ def test_if_present
790
+ assert_nil t(@myung, @comments.if_present)
791
+ assert_equal 0, t(@myung, @comments.if_present.count)
792
+ assert_equal 20.16, t(@myung, @score.if_present)
793
+ assert_equal '2016-05-23', t(@myung, @created_at.if_present.format('%Y-%m-%d'))
794
+ assert_equal '2016-05-23', t(@myung, @created_at.if_present.format_date('%Y-%m-%d'))
795
+ assert_nil t(@laure, @comments.if_present)
796
+
797
+ assert_nil t(@nilly, @duration.if_present.format('%Y-%m-%d'))
798
+ assert_nil t(@nilly, @duration.if_present.format_date('%Y-%m-%d'))
799
+
800
+ # NOTE: here we're testing the capacity to format a nil value,
801
+ # however, @comments is a text field, and not a date/datetime field,
802
+ # so Postgres will rightfully complain when we format the text:
803
+ # we need to cast it first.
804
+ if @env_db == 'postgresql'
805
+ assert_nil t(@laure, @comments.cast(:date).if_present.format('%Y-%m-%d'))
806
+ assert_nil t(@laure, @comments.cast(:date).if_present.format_date('%Y-%m-%d'))
807
+ else
808
+ assert_nil t(@laure, @comments.if_present.format('%Y-%m-%d'))
809
+ assert_nil t(@laure, @comments.if_present.format_date('%Y-%m-%d'))
810
+ end
811
+ end
812
+
693
813
  def test_is_null
694
814
  # puts User.where(@age.is_null).select(@name).to_sql
695
815
  # puts @age.is_null
@@ -725,7 +845,7 @@ module ArelExtensions
725
845
  def test_math_minus
726
846
  d = Date.new(2016, 5, 20)
727
847
  # Datediff
728
- assert_equal 9, User.where((@created_at - @created_at).eq(0)).count
848
+ assert_equal 10, User.where((@created_at - @created_at).eq(0)).count
729
849
  assert_equal 3, @laure.select((@created_at - d).as('res')).first.res.abs.to_i
730
850
  # Substraction
731
851
  assert_equal 0, User.where((@age - 10).eq(50)).count
@@ -845,8 +965,8 @@ module ArelExtensions
845
965
 
846
966
  def test_subquery_with_order
847
967
  skip if ['mssql'].include?(@env_db) && Arel::VERSION.to_i < 10
848
- assert_equal 9, User.where(name: User.select(:name).order(:name)).count
849
- assert_equal 9, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
968
+ assert_equal 10, User.where(name: User.select(:name).order(:name)).count
969
+ assert_equal 10, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
850
970
  if !['mysql'].include?(@env_db) # MySql can't have limit in IN subquery
851
971
  assert_equal 2, User.where(name: User.select(:name).order(:name).limit(2)).count
852
972
  # assert_equal 6, User.where(name: User.select(:name).order(:name).offset(2)).count
data/version_v1.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = '1.3.5'.freeze
2
+ VERSION = '1.3.7'.freeze
3
3
  end
data/version_v2.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = '2.1.5'.freeze
2
+ VERSION = '2.1.7'.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.5
4
+ version: 2.1.7
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-07-25 00:00:00.000000000 Z
13
+ date: 2023-01-27 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,6 +72,7 @@ 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
@@ -94,8 +81,8 @@ files:
94
81
  - arel_extensions.gemspec
95
82
  - functions.html
96
83
  - gemfiles/rails3.gemfile
97
- - gemfiles/rails4.gemfile
98
- - gemfiles/rails5_0.gemfile
84
+ - gemfiles/rails4_2.gemfile
85
+ - gemfiles/rails5.gemfile
99
86
  - gemfiles/rails5_1_4.gemfile
100
87
  - gemfiles/rails5_2.gemfile
101
88
  - gemfiles/rails6.gemfile
@@ -136,6 +123,7 @@ files:
136
123
  - lib/arel_extensions/nodes/find_in_set.rb
137
124
  - lib/arel_extensions/nodes/floor.rb
138
125
  - lib/arel_extensions/nodes/format.rb
126
+ - lib/arel_extensions/nodes/formatted_date.rb
139
127
  - lib/arel_extensions/nodes/formatted_number.rb
140
128
  - lib/arel_extensions/nodes/function.rb
141
129
  - lib/arel_extensions/nodes/is_null.rb
@@ -150,7 +138,9 @@ files:
150
138
  - lib/arel_extensions/nodes/rand.rb
151
139
  - lib/arel_extensions/nodes/repeat.rb
152
140
  - lib/arel_extensions/nodes/replace.rb
141
+ - lib/arel_extensions/nodes/rollup.rb
153
142
  - lib/arel_extensions/nodes/round.rb
143
+ - lib/arel_extensions/nodes/select.rb
154
144
  - lib/arel_extensions/nodes/soundex.rb
155
145
  - lib/arel_extensions/nodes/std.rb
156
146
  - lib/arel_extensions/nodes/substring.rb
@@ -218,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
208
  - !ruby/object:Gem::Version
219
209
  version: '0'
220
210
  requirements: []
221
- rubygems_version: 3.2.3
211
+ rubygems_version: 3.3.5
222
212
  signing_key:
223
213
  specification_version: 4
224
214
  summary: Extending Arel