arel_extensions 2.0.21 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +153 -72
  3. data/README.md +42 -0
  4. data/arel_extensions.gemspec +1 -1
  5. data/gemfiles/rails5_2.gemfile +6 -5
  6. data/gemfiles/rails6.gemfile +6 -6
  7. data/gemfiles/rails6_1.gemfile +5 -5
  8. data/gemfiles/rails7.gemfile +30 -0
  9. data/gemspecs/arel_extensions-v1.gemspec +1 -1
  10. data/gemspecs/arel_extensions-v2.gemspec +1 -1
  11. data/lib/arel_extensions/aliases.rb +14 -0
  12. data/lib/arel_extensions/attributes.rb +2 -0
  13. data/lib/arel_extensions/insert_manager.rb +19 -17
  14. data/lib/arel_extensions/math.rb +16 -16
  15. data/lib/arel_extensions/nodes/case.rb +2 -1
  16. data/lib/arel_extensions/nodes/cast.rb +1 -1
  17. data/lib/arel_extensions/nodes/function.rb +4 -2
  18. data/lib/arel_extensions/nodes/json.rb +3 -1
  19. data/lib/arel_extensions/nodes/length.rb +6 -0
  20. data/lib/arel_extensions/nodes/replace.rb +0 -8
  21. data/lib/arel_extensions/nodes/union.rb +1 -1
  22. data/lib/arel_extensions/nodes/union_all.rb +1 -1
  23. data/lib/arel_extensions/string_functions.rb +10 -2
  24. data/lib/arel_extensions/version.rb +1 -1
  25. data/lib/arel_extensions/visitors/mssql.rb +1 -1
  26. data/lib/arel_extensions/visitors/mysql.rb +9 -2
  27. data/lib/arel_extensions/visitors/oracle.rb +1 -1
  28. data/lib/arel_extensions/visitors/postgresql.rb +13 -7
  29. data/lib/arel_extensions/visitors/to_sql.rb +14 -9
  30. data/lib/arel_extensions/visitors.rb +9 -1
  31. data/lib/arel_extensions.rb +52 -14
  32. data/test/real_db_test.rb +5 -1
  33. data/test/visitors/test_to_sql.rb +18 -11
  34. data/test/with_ar/all_agnostic_test.rb +14 -4
  35. data/test/with_ar/insert_agnostic_test.rb +6 -2
  36. data/test/with_ar/test_bulk_sqlite.rb +6 -2
  37. data/test/with_ar/test_math_sqlite.rb +6 -2
  38. data/test/with_ar/test_string_mysql.rb +6 -2
  39. data/test/with_ar/test_string_sqlite.rb +6 -2
  40. data/version_v1.rb +1 -1
  41. data/version_v2.rb +1 -1
  42. metadata +9 -7
@@ -46,7 +46,9 @@ module ArelExtensions
46
46
  when DateTime, Time
47
47
  convert_to_node(n.strftime("%Y-%m-%dT%H:%M:%S.%L%:z"))
48
48
  when NilClass
49
- Arel.sql('null')
49
+ Arel.null
50
+ when Arel::SelectManager
51
+ Arel.grouping(n)
50
52
  else
51
53
  convert_to_node(n)
52
54
  end
@@ -2,6 +2,12 @@ module ArelExtensions
2
2
  module Nodes
3
3
  class Length < Function
4
4
  RETURN_TYPE = :integer
5
+ attr_accessor :bytewise
6
+
7
+ def initialize(node, bytewise = true)
8
+ @bytewise = bytewise
9
+ super([node])
10
+ end
5
11
  end
6
12
  end
7
13
  end
@@ -10,10 +10,6 @@ module ArelExtensions
10
10
  @substitute = convert_to_node(substitute)
11
11
  super([@left,@pattern,@substitute])
12
12
  end
13
-
14
- def +(other)
15
- return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
16
- end
17
13
  end
18
14
 
19
15
  class RegexpReplace < Function
@@ -26,10 +22,6 @@ module ArelExtensions
26
22
  @substitute = convert_to_node(substitute)
27
23
  super([@left,@pattern,@substitute])
28
24
  end
29
-
30
- def +(other)
31
- return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
32
- end
33
25
  end
34
26
  end
35
27
  end
@@ -14,7 +14,7 @@ module ArelExtensions
14
14
  end
15
15
 
16
16
  def as other
17
- Arel::Nodes::TableAlias.new Arel::Nodes::Grouping.new(self), Arel::Nodes::SqlLiteral.new(other.to_s)
17
+ Arel::Nodes::TableAlias.new Arel.grouping(self), Arel::Nodes::SqlLiteral.new(other.to_s)
18
18
  end
19
19
  end
20
20
  end
@@ -10,7 +10,7 @@ module ArelExtensions
10
10
  end
11
11
 
12
12
  def as other
13
- Arel::Nodes::TableAlias.new Arel::Nodes::Grouping.new(self), Arel::Nodes::SqlLiteral.new(other.to_s)
13
+ Arel::Nodes::TableAlias.new Arel.grouping(self), Arel::Nodes::SqlLiteral.new(other.to_s)
14
14
  end
15
15
  end
16
16
  end
@@ -24,9 +24,17 @@ module ArelExtensions
24
24
  ArelExtensions::Nodes::FindInSet.new [other, self]
25
25
  end
26
26
 
27
- # LENGTH function returns the length of the value in a text field.
27
+ # LENGTH function returns the length (bytewise) of the value in a text field.
28
28
  def length
29
- ArelExtensions::Nodes::Length.new [self]
29
+ ArelExtensions::Nodes::Length.new self, true
30
+ end
31
+
32
+ def byte_length
33
+ ArelExtensions::Nodes::Length.new self, true
34
+ end
35
+
36
+ def char_length
37
+ ArelExtensions::Nodes::Length.new self, false
30
38
  end
31
39
 
32
40
  # LOCATE function returns the first starting position of a string in another string.
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = "2.0.21".freeze
2
+ VERSION = "2.1.0".freeze
3
3
  end
@@ -155,7 +155,7 @@ module ArelExtensions
155
155
  end
156
156
 
157
157
  def visit_ArelExtensions_Nodes_Length o, collector
158
- collector << "LEN("
158
+ collector << "#{o.bytewise ? 'DATALENGTH' : 'LEN'}("
159
159
  collector = visit o.expr, collector
160
160
  collector << ")"
161
161
  collector
@@ -354,9 +354,16 @@ module ArelExtensions
354
354
  else
355
355
  collector = visit o.left, collector
356
356
  end
357
- collector << " AS `"
357
+ collector << " AS "
358
+
359
+ # sometimes these values are already quoted, if they are, don't double quote it
360
+ quote = o.right.is_a?(Arel::Nodes::SqlLiteral) && o.right[0] != '`' && o.right[-1] != '`'
361
+
362
+ collector << '`' if quote
358
363
  collector = visit o.right, collector
359
- collector << "`"
364
+ collector << '`' if quote
365
+
366
+ collector
360
367
  collector
361
368
  end
362
369
 
@@ -308,7 +308,7 @@ module ArelExtensions
308
308
  end
309
309
 
310
310
  def visit_ArelExtensions_Nodes_Length o, collector
311
- collector << "LENGTH("
311
+ collector << "LENGTH#{o.bytewise ? 'B' : ''}("
312
312
  collector = visit o.expr, collector
313
313
  collector << ")"
314
314
  collector
@@ -86,9 +86,15 @@ module ArelExtensions
86
86
  else
87
87
  collector = visit o.left, collector
88
88
  end
89
- collector << " AS \""
89
+ collector << " AS "
90
+
91
+ # sometimes these values are already quoted, if they are, don't double quote it
92
+ quote = o.right.is_a?(Arel::Nodes::SqlLiteral) && o.right[0] != '"' && o.right[-1] != '"'
93
+
94
+ collector << '"' if quote
90
95
  collector = visit o.right, collector
91
- collector << "\""
96
+ collector << '"' if quote
97
+
92
98
  collector
93
99
  end
94
100
 
@@ -373,6 +379,8 @@ module ArelExtensions
373
379
  Arel::Nodes::SqlLiteral.new('date')
374
380
  when :binary
375
381
  Arel::Nodes::SqlLiteral.new('binary')
382
+ when :jsonb
383
+ Arel::Nodes::SqlLiteral.new('jsonb')
376
384
  else
377
385
  Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
378
386
  end
@@ -401,13 +409,13 @@ module ArelExtensions
401
409
  ArelExtensions::Nodes::Concat.new([
402
410
  Arel::Nodes::NamedFunction.new('TRIM',[
403
411
  Arel::Nodes::NamedFunction.new('TO_CHAR',[
404
- col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
412
+ Arel.when(col.not_eq 0).then(col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)).else(1),
405
413
  Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
406
414
  ])]),
407
415
  o.type,
408
416
  Arel::Nodes::NamedFunction.new('TRIM',[
409
417
  Arel::Nodes::NamedFunction.new('TO_CHAR',[
410
- col.abs.log10.floor,
418
+ Arel.when(col.not_eq 0).then(col.abs.log10.floor).else(0),
411
419
  Arel::Nodes.build_quoted('FM'+nines_before)
412
420
  ])])
413
421
  ])
@@ -511,8 +519,6 @@ module ArelExtensions
511
519
  collector << '::jsonb'
512
520
  when NilClass
513
521
  collector << %Q['null'::jsonb]
514
- when Arel::Attributes::Attribute
515
- collector = visit o.dict.cast(:jsonb), collector
516
522
  else
517
523
  collector = visit o.dict, collector
518
524
  collector << '::jsonb'
@@ -532,7 +538,7 @@ module ArelExtensions
532
538
 
533
539
  def visit_ArelExtensions_Nodes_JsonGet o,collector
534
540
  collector = visit o.dict, collector
535
- collector << ' -> '
541
+ collector << ' ->> '
536
542
  collector = visit o.key, collector
537
543
  collector
538
544
  end
@@ -8,10 +8,15 @@ module ArelExtensions
8
8
  def make_json_string expr
9
9
  Arel::Nodes.build_quoted('"') \
10
10
  + expr
11
+ .coalesce('')
11
12
  .replace('\\','\\\\').replace('"','\"').replace("\n", '\n') \
12
13
  + '"'
13
14
  end
14
15
 
16
+ def make_json_null
17
+ Arel::Nodes.build_quoted("null")
18
+ end
19
+
15
20
  # Math Functions
16
21
  def visit_ArelExtensions_Nodes_Abs o, collector
17
22
  collector << "ABS("
@@ -117,7 +122,7 @@ module ArelExtensions
117
122
  end
118
123
 
119
124
  def visit_ArelExtensions_Nodes_Length o, collector
120
- collector << "LENGTH("
125
+ collector << "#{o.bytewise ? '' : 'CHAR_'}LENGTH("
121
126
  collector = visit o.left, collector
122
127
  collector << ")"
123
128
  collector
@@ -601,20 +606,20 @@ module ArelExtensions
601
606
  def json_value(o,v)
602
607
  case o.type_of_node(v)
603
608
  when :string
604
- Arel.when(v.is_null).then(Arel::Nodes.build_quoted("null")).else(make_json_string(v))
609
+ Arel.when(v.is_null).then(make_json_null).else(make_json_string(v))
605
610
  when :date
606
611
  s = v.format('%Y-%m-%d')
607
- Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
612
+ Arel.when(s.is_null).then(make_json_null).else(make_json_string(s))
608
613
  when :datetime
609
614
  s = v.format('%Y-%m-%dT%H:%M:%S')
610
- Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
615
+ Arel.when(s.is_null).then(make_json_null).else(make_json_string(s))
611
616
  when :time
612
617
  s = v.format('%H:%M:%S')
613
- Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
618
+ Arel.when(s.is_null).then(make_json_null).else(make_json_string(s))
614
619
  when :nil
615
- Arel::Nodes.build_quoted("null")
620
+ make_json_null
616
621
  else
617
- ArelExtensions::Nodes::Cast.new([v, :string]).coalesce("null")
622
+ ArelExtensions::Nodes::Cast.new([v, :string]).coalesce(make_json_null)
618
623
  end
619
624
  end
620
625
 
@@ -636,7 +641,7 @@ module ArelExtensions
636
641
  if i != 0
637
642
  res += ', '
638
643
  end
639
- res += make_json_string(ArelExtensions::Nodes::Cast.new([k, :string]).coalesce("")) + ': '
644
+ res += make_json_string(ArelExtensions::Nodes::Cast.new([k, :string])) + ': '
640
645
  res += json_value(o,v)
641
646
  end
642
647
  res += '}'
@@ -658,7 +663,7 @@ module ArelExtensions
658
663
  if i != 0
659
664
  res = res + ', '
660
665
  end
661
- kv = make_json_string(ArelExtensions::Nodes::Cast.new([k, :string]).coalesce("")) + ': '
666
+ kv = make_json_string(ArelExtensions::Nodes::Cast.new([k, :string])) + ': '
662
667
  kv += json_value(o,v)
663
668
  res = res + kv.group_concat(', ', order: Array(orders)).coalesce('')
664
669
  end
@@ -9,9 +9,17 @@ if defined?(Arel::Visitors::Oracle)
9
9
  require 'arel_extensions/visitors/oracle12'
10
10
  end
11
11
 
12
- if defined?(Arel::Visitors::MSSQL)
12
+ if defined?(Arel::Visitors::SQLServer) || defined?(Arel::Visitors::MSSQL)
13
13
  require 'arel_extensions/visitors/mssql'
14
+ end
14
15
 
16
+ if defined?(Arel::Visitors::SQLServer)
17
+ class Arel::Visitors::SQLServer
18
+ include ArelExtensions::Visitors::MSSQL
19
+ end
20
+ end
21
+
22
+ if defined?(Arel::Visitors::MSSQL)
15
23
  class Arel::Visitors::MSSQL
16
24
  include ArelExtensions::Visitors::MSSQL
17
25
 
@@ -34,9 +34,9 @@ class Arel::Nodes::Grouping
34
34
  end
35
35
 
36
36
  class Arel::Nodes::Ordering
37
- def eql? other
38
- self.hash.eql? other.hash
39
- end
37
+ def eql? other
38
+ self.hash.eql? other.hash
39
+ end
40
40
  end
41
41
 
42
42
  class Arel::Nodes::Function
@@ -52,6 +52,7 @@ if Gem::Version.new(Arel::VERSION) >= Gem::Version.new("7.1.0")
52
52
  end
53
53
 
54
54
  require 'arel_extensions/version'
55
+ require 'arel_extensions/aliases'
55
56
  require 'arel_extensions/attributes'
56
57
  require 'arel_extensions/visitors'
57
58
  require 'arel_extensions/nodes'
@@ -88,11 +89,13 @@ module Arel
88
89
  end
89
90
 
90
91
  def self.json *expr
91
- if expr.length == 1
92
- ArelExtensions::Nodes::Json.new(expr.first)
93
- else
94
- ArelExtensions::Nodes::Json.new(expr)
95
- end
92
+ ArelExtensions::Nodes::Json.new(
93
+ if expr.length == 1
94
+ expr.first
95
+ else
96
+ expr
97
+ end
98
+ )
96
99
  end
97
100
 
98
101
  def self.when condition
@@ -100,20 +103,31 @@ module Arel
100
103
  end
101
104
 
102
105
  def self.duration s, expr
103
- ArelExtensions::Nodes::Duration.new(s.to_s+'i',expr)
106
+ ArelExtensions::Nodes::Duration.new("#{s}i", expr)
107
+ end
108
+
109
+ def self.grouping *v
110
+ Arel::Nodes::Grouping.new(*v)
104
111
  end
105
112
 
113
+ # The TRUE pseudo literal.
106
114
  def self.true
107
- Arel::Nodes::Equality.new(1,1)
115
+ Arel::Nodes::Equality.new(1, 1)
108
116
  end
109
117
 
118
+ # The FALSE pseudo literal.
110
119
  def self.false
111
- Arel::Nodes::Equality.new(1,0)
120
+ Arel::Nodes::Equality.new(1, 0)
121
+ end
122
+
123
+ # The NULL literal.
124
+ def self.null
125
+ Arel::Nodes.build_quoted(nil)
112
126
  end
113
127
 
114
128
  def self.tuple *v
115
- tmp = Arel::Nodes::Grouping.new(nil)
116
- Arel::Nodes::Grouping.new(v.map{|e| tmp.convert_to_node(e)})
129
+ tmp = Arel.grouping(nil)
130
+ Arel.grouping v.map{|e| tmp.convert_to_node(e)}
117
131
  end
118
132
  end
119
133
 
@@ -123,6 +137,7 @@ class Arel::Attributes::Attribute
123
137
  end
124
138
 
125
139
  class Arel::Nodes::Function
140
+ include ArelExtensions::Aliases
126
141
  include ArelExtensions::Math
127
142
  include ArelExtensions::Comparators
128
143
  include ArelExtensions::DateDuration
@@ -158,6 +173,9 @@ class Arel::Nodes::Unary
158
173
  include ArelExtensions::MathFunctions
159
174
  include ArelExtensions::Comparators
160
175
  include ArelExtensions::Predications
176
+ def eql? other
177
+ hash == other.hash
178
+ end
161
179
  end
162
180
 
163
181
  class Arel::Nodes::Binary
@@ -167,6 +185,9 @@ class Arel::Nodes::Binary
167
185
  include ArelExtensions::Comparators
168
186
  include ArelExtensions::BooleanFunctions
169
187
  include ArelExtensions::Predications
188
+ def eql? other
189
+ hash == other.hash
190
+ end
170
191
  end
171
192
 
172
193
  class Arel::Nodes::Equality
@@ -183,6 +204,19 @@ end
183
204
  class Arel::SelectManager
184
205
  include ArelExtensions::SetFunctions
185
206
  include ArelExtensions::Nodes
207
+
208
+ def as table_name
209
+ Arel::Nodes::TableAlias.new(self, table_name)
210
+ end
211
+
212
+ # Install an alias, if present.
213
+ def xas table_name
214
+ if table_name.present?
215
+ as table_name
216
+ else
217
+ self
218
+ end
219
+ end
186
220
  end
187
221
 
188
222
  class Arel::Nodes::As
@@ -192,7 +226,11 @@ end
192
226
  class Arel::Table
193
227
  alias_method(:old_alias, :alias) rescue nil
194
228
  def alias(name = "#{self.name}_2")
195
- name.blank? ? self : Arel::Nodes::TableAlias.new(self,name)
229
+ if name.present?
230
+ Arel::Nodes::TableAlias.new(self, name)
231
+ else
232
+ self
233
+ end
196
234
  end
197
235
  end
198
236
 
data/test/real_db_test.rb CHANGED
@@ -8,7 +8,11 @@ require 'arel_extensions'
8
8
  def setup_db
9
9
  ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
10
10
  ActiveRecord::Base.establish_connection(ENV['DB'].try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
11
- ActiveRecord::Base.default_timezone = :utc
11
+ if ActiveRecord::VERSION::MAJOR >= 7
12
+ ActiveRecord.default_timezone = :utc
13
+ else
14
+ ActiveRecord::Base.default_timezone = :utc
15
+ end
12
16
  @cnx = ActiveRecord::Base.connection
13
17
  if ActiveRecord::Base.connection.adapter_name =~ /sqlite/i
14
18
  $sqlite = true
@@ -282,16 +282,23 @@ module ArelExtensions
282
282
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END ILIKE 'value'}
283
283
  end
284
284
 
285
- it "should be possible to use as on anything" do
286
- _(compile(@table[:name].as('alias'))).must_be_like %{"users"."name" AS alias}
287
- _(compile(@table[:name].concat(' test').as('alias'))).must_be_like %{CONCAT("users"."name", ' test') AS alias}
288
- _(compile((@table[:name] + ' test').as('alias'))).must_be_like %{CONCAT("users"."name", ' test') AS alias}
289
- _(compile((@table[:age] + 42).as('alias'))).must_be_like %{("users"."age" + 42) AS alias}
290
- _(compile(@table[:name].coalesce('').as('alias'))).must_be_like %{COALESCE("users"."name", '') AS alias}
291
- _(compile(Arel::Nodes.build_quoted('test').as('alias'))).must_be_like %{'test' AS alias}
292
- _(compile(@table.project(@table[:name]).as('alias'))).must_be_like %{(SELECT "users"."name" FROM "users") alias}
293
- _(compile(@table[:name].when("smith").then("cool").else("uncool").as('alias')))
294
- .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END AS alias}
285
+ it "should be possible to use as/xas on anything" do
286
+ {
287
+ @table[:name] => %{"users"."name" AS alias},
288
+ @table[:name].concat(' test') => %{CONCAT("users"."name", ' test') AS alias},
289
+ (@table[:name] + ' test') => %{CONCAT("users"."name", ' test') AS alias},
290
+ (@table[:age] + 42) => %{("users"."age" + 42) AS alias},
291
+ @table[:name].coalesce('') => %{COALESCE("users"."name", '') AS alias},
292
+ Arel::Nodes.build_quoted('test') => %{'test' AS alias},
293
+ @table.project(@table[:name]) => %{(SELECT "users"."name" FROM "users") "alias"},
294
+ @table[:name].when("smith").then("cool").else("uncool") => %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END AS alias},
295
+ }.each do |exp, res|
296
+ _(compile(exp.as('alias'))).must_be_like res
297
+ _(compile(exp.xas('alias'))).must_be_like res
298
+
299
+ res_no_alias = res.gsub(/\s*(?:AS alias|"alias")\s*\z/, '')
300
+ _(compile(exp.xas(nil))).must_be_like res_no_alias
301
+ end
295
302
  end
296
303
 
297
304
  it "should accept comparators on functions" do
@@ -373,7 +380,7 @@ module ArelExtensions
373
380
  end
374
381
 
375
382
  it "should respecting Grouping" do
376
- g = ->(*v) { Arel::Nodes::Grouping.new(v) }
383
+ g = ->(*v) { Arel.grouping(v) }
377
384
  _(compile(g[@table[:id], @table[:age]].in [g[1, 42]]))
378
385
  .must_be_like %{("users"."id", "users"."age") IN ((1, 42))}
379
386
  _(compile(g[@table[:id], @table[:age]].in [g[1, 42], g[2, 51]]))
@@ -2,7 +2,7 @@ require 'arelx_test_helper'
2
2
  require 'date'
3
3
 
4
4
  module ArelExtensions
5
- module WthAr
5
+ module WithAr
6
6
  class ListTest < Minitest::Test
7
7
  require 'minitest/pride'
8
8
  def connect_db
@@ -14,7 +14,11 @@ module ArelExtensions
14
14
  @env_db = ENV['DB']
15
15
  end
16
16
  ActiveRecord::Base.establish_connection(@env_db.try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
17
- ActiveRecord::Base.default_timezone = :utc
17
+ if ActiveRecord::VERSION::MAJOR >= 7
18
+ ActiveRecord.default_timezone = :utc
19
+ else
20
+ ActiveRecord::Base.default_timezone = :utc
21
+ end
18
22
  @cnx = ActiveRecord::Base.connection
19
23
  $sqlite = @cnx.adapter_name =~ /sqlite/i
20
24
  $load_extension_disabled ||= false
@@ -166,6 +170,12 @@ module ArelExtensions
166
170
  # Since Arel10 (Rails6.1), some unwanted behaviors on aggregated calculation were present.
167
171
  # This should works no matter which version of rails is used
168
172
  assert User.group(:score).average(:id).values.all?{|e| !e.nil?}
173
+
174
+ # Since Rails 7, a patch to calculations.rb has tirggered a double
175
+ # quoting of the alias name. See https://github.com/rails/rails/commit/7e6e9091e55c3357b0162d44b6ab955ed0c718d5
176
+ # Before the patch that fixed this the following error would occur:
177
+ # ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: zero-length delimited identifier at or near """"
178
+ assert User.group(:score).count(:id).values.all?{|e| !e.nil?}
169
179
  end
170
180
 
171
181
  # String Functions
@@ -358,7 +368,6 @@ module ArelExtensions
358
368
 
359
369
  def test_format
360
370
  assert_equal '2016-05-23', t(@lucas, @created_at.format('%Y-%m-%d'))
361
- skip "SQL Server does not accept any format" if @env_db == 'mssql'
362
371
  assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S'))
363
372
  assert_equal '12:42%', t(@lucas, @updated_at.format('%R%%'))
364
373
  end
@@ -500,7 +509,8 @@ module ArelExtensions
500
509
  assert_equal Time, t(@lucas,@updated_at.cast(:string).cast(:datetime)).class
501
510
  assert_equal Time, t(@lucas,@updated_at.cast(:time)).class
502
511
 
503
- assert_equal "2014-03-03 12:42:00", t(@lucas,@updated_at.cast(:string)) unless @env_db == 'mssql' # locale dependent
512
+ # mysql adapter in rails7 adds some infos we just squeeze here
513
+ assert_equal "2014-03-03 12:42:00", t(@lucas,@updated_at.cast(:string)).split('.').first unless @env_db == 'mssql' # locale dependent
504
514
  assert_equal Date.parse("2014-03-03"), t(@lucas,Arel::Nodes.build_quoted('2014-03-03').cast(:date))
505
515
  assert_equal Date.parse("5014-03-03"), t(@lucas,(@age.cast(:string) + '014-03-03').cast(:date))
506
516
  assert_equal Time.parse("2014-03-03 12:42:00 UTC"), t(@lucas,@updated_at.cast(:string).cast(:datetime))
@@ -2,7 +2,7 @@ require 'arelx_test_helper'
2
2
  require 'date'
3
3
 
4
4
  module ArelExtensions
5
- module WthAr
5
+ module WithAr
6
6
  class InsertManagerTest < Minitest::Test
7
7
  def setup_db
8
8
  ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
@@ -13,7 +13,11 @@ module ArelExtensions
13
13
  @env_db = ENV['DB']
14
14
  end
15
15
  ActiveRecord::Base.establish_connection(@env_db.try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
16
- ActiveRecord::Base.default_timezone = :utc
16
+ if ActiveRecord::VERSION::MAJOR >= 7
17
+ ActiveRecord.default_timezone = :utc
18
+ else
19
+ ActiveRecord::Base.default_timezone = :utc
20
+ end
17
21
  @cnx = ActiveRecord::Base.connection
18
22
  Arel::Table.engine = ActiveRecord::Base
19
23
  if File.exist?("init/#{@env_db}.sql")
@@ -1,12 +1,16 @@
1
1
  require 'arelx_test_helper'
2
2
 
3
3
  module ArelExtensions
4
- module WthAr
4
+ module WithAr
5
5
  describe 'the sqlite visitor' do
6
6
  before do
7
7
  ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
8
8
  ActiveRecord::Base.establish_connection(ENV['DB'] || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
9
- ActiveRecord::Base.default_timezone = :utc
9
+ if ActiveRecord::VERSION::MAJOR >= 7
10
+ ActiveRecord.default_timezone = :utc
11
+ else
12
+ ActiveRecord::Base.default_timezone = :utc
13
+ end
10
14
  @cnx = ActiveRecord::Base.connection
11
15
  Arel::Table.engine = ActiveRecord::Base
12
16
  @cnx.drop_table(:users) rescue nil
@@ -1,12 +1,16 @@
1
1
  require 'arelx_test_helper'
2
2
 
3
3
  module ArelExtensions
4
- module WthAr
4
+ module WithAr
5
5
  describe 'the sqlite visitor can do maths' do
6
6
  before do
7
7
  ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
8
8
  ActiveRecord::Base.establish_connection(ENV['DB'] || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
9
- ActiveRecord::Base.default_timezone = :utc
9
+ if ActiveRecord::VERSION::MAJOR >= 7
10
+ ActiveRecord.default_timezone = :utc
11
+ else
12
+ ActiveRecord::Base.default_timezone = :utc
13
+ end
10
14
  Arel::Table.engine = ActiveRecord::Base
11
15
  @cnx = ActiveRecord::Base.connection
12
16
  @cnx.drop_table(:users) rescue nil
@@ -2,12 +2,16 @@ require 'arelx_test_helper'
2
2
  require 'date'
3
3
 
4
4
  module ArelExtensions
5
- module WthAr
5
+ module WithAr
6
6
  describe 'the mysql visitor can do string operations' do
7
7
  before do
8
8
  ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
9
9
  ActiveRecord::Base.establish_connection(ENV['DB'] || (RUBY_PLATFORM == 'java' ? :"jdbc-mysql" : :mysql))
10
- ActiveRecord::Base.default_timezone = :utc
10
+ if ActiveRecord::VERSION::MAJOR >= 7
11
+ ActiveRecord.default_timezone = :utc
12
+ else
13
+ ActiveRecord::Base.default_timezone = :utc
14
+ end
11
15
  begin
12
16
  @cnx = ActiveRecord::Base.connection
13
17
  rescue => e
@@ -2,12 +2,16 @@ require 'arelx_test_helper'
2
2
  require 'date'
3
3
 
4
4
  module ArelExtensions
5
- module WthAr
5
+ module WithAr
6
6
  describe 'the sqlite visitor can do string operations' do
7
7
  before do
8
8
  ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
9
9
  ActiveRecord::Base.establish_connection(ENV['DB'] || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
10
- ActiveRecord::Base.default_timezone = :utc
10
+ if ActiveRecord::VERSION::MAJOR >= 7
11
+ ActiveRecord.default_timezone = :utc
12
+ else
13
+ ActiveRecord::Base.default_timezone = :utc
14
+ end
11
15
  @cnx = ActiveRecord::Base.connection
12
16
  Arel::Table.engine = ActiveRecord::Base
13
17
  @cnx.drop_table(:users) rescue nil
data/version_v1.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = "1.2.24".freeze
2
+ VERSION = "1.3.0".freeze
3
3
  end
data/version_v2.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = "2.0.21".freeze
2
+ VERSION = "2.1.0".freeze
3
3
  end