arel_extensions 2.0.22 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +358 -71
  3. data/Gemfile +8 -8
  4. data/README.md +86 -0
  5. data/arel_extensions.gemspec +1 -1
  6. data/gemfiles/rails5_2.gemfile +8 -7
  7. data/gemfiles/rails6.gemfile +7 -8
  8. data/gemfiles/rails6_1.gemfile +6 -7
  9. data/gemfiles/rails7.gemfile +22 -0
  10. data/gemspecs/arel_extensions-v1.gemspec +1 -1
  11. data/gemspecs/arel_extensions-v2.gemspec +1 -1
  12. data/lib/arel_extensions/aliases.rb +14 -0
  13. data/lib/arel_extensions/attributes.rb +2 -0
  14. data/lib/arel_extensions/date_duration.rb +2 -2
  15. data/lib/arel_extensions/helpers.rb +48 -0
  16. data/lib/arel_extensions/insert_manager.rb +19 -17
  17. data/lib/arel_extensions/math.rb +22 -32
  18. data/lib/arel_extensions/nodes/case.rb +5 -6
  19. data/lib/arel_extensions/nodes/cast.rb +1 -1
  20. data/lib/arel_extensions/nodes/date_diff.rb +23 -4
  21. data/lib/arel_extensions/nodes/format.rb +3 -2
  22. data/lib/arel_extensions/nodes/function.rb +2 -6
  23. data/lib/arel_extensions/nodes/json.rb +3 -1
  24. data/lib/arel_extensions/nodes/replace.rb +0 -8
  25. data/lib/arel_extensions/nodes/union.rb +1 -1
  26. data/lib/arel_extensions/nodes/union_all.rb +1 -1
  27. data/lib/arel_extensions/version.rb +1 -1
  28. data/lib/arel_extensions/visitors/mssql.rb +109 -51
  29. data/lib/arel_extensions/visitors/mysql.rb +15 -2
  30. data/lib/arel_extensions/visitors/oracle.rb +6 -1
  31. data/lib/arel_extensions/visitors/postgresql.rb +20 -10
  32. data/lib/arel_extensions/visitors/sqlite.rb +6 -3
  33. data/lib/arel_extensions/visitors/to_sql.rb +13 -8
  34. data/lib/arel_extensions/visitors.rb +9 -1
  35. data/lib/arel_extensions.rb +57 -15
  36. data/test/arelx_test_helper.rb +45 -0
  37. data/test/database.yml +8 -2
  38. data/test/real_db_test.rb +5 -1
  39. data/test/support/fake_record.rb +1 -1
  40. data/test/visitors/test_to_sql.rb +39 -11
  41. data/test/with_ar/all_agnostic_test.rb +79 -6
  42. data/test/with_ar/insert_agnostic_test.rb +6 -2
  43. data/test/with_ar/test_bulk_sqlite.rb +6 -2
  44. data/test/with_ar/test_math_sqlite.rb +6 -2
  45. data/test/with_ar/test_string_mysql.rb +6 -2
  46. data/test/with_ar/test_string_sqlite.rb +6 -2
  47. data/version_v1.rb +1 -1
  48. data/version_v2.rb +1 -1
  49. metadata +10 -8
  50. data/appveyor.yml +0 -44
@@ -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'
@@ -76,7 +77,17 @@ require 'arel_extensions/nodes/soundex'
76
77
  require 'arel_extensions/nodes/cast'
77
78
  require 'arel_extensions/nodes/json'
78
79
 
79
-
80
+ # It seems like the code in lib/arel_extensions/visitors.rb that is supposed
81
+ # to inject ArelExtension is not enough. Different versions of the sqlserver
82
+ # adapter behave differently. It doesn't always proc, so we added this for
83
+ # coverage.
84
+ if defined?(Arel::Visitors::SQLServer)
85
+ Arel::Visitors.const_set('MSSQL', Arel::Visitors::SQLServer)
86
+ require 'arel_extensions/visitors/mssql'
87
+ class Arel::Visitors::SQLServer
88
+ include ArelExtensions::Visitors::MSSQL
89
+ end
90
+ end
80
91
 
81
92
  module Arel
82
93
  def self.rand
@@ -88,11 +99,13 @@ module Arel
88
99
  end
89
100
 
90
101
  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
102
+ ArelExtensions::Nodes::Json.new(
103
+ if expr.length == 1
104
+ expr.first
105
+ else
106
+ expr
107
+ end
108
+ )
96
109
  end
97
110
 
98
111
  def self.when condition
@@ -100,20 +113,31 @@ module Arel
100
113
  end
101
114
 
102
115
  def self.duration s, expr
103
- ArelExtensions::Nodes::Duration.new(s.to_s+'i',expr)
116
+ ArelExtensions::Nodes::Duration.new("#{s}i", expr)
104
117
  end
105
118
 
119
+ def self.grouping *v
120
+ Arel::Nodes::Grouping.new(*v)
121
+ end
122
+
123
+ # The TRUE pseudo literal.
106
124
  def self.true
107
- Arel::Nodes::Equality.new(1,1)
125
+ Arel::Nodes::Equality.new(1, 1)
108
126
  end
109
127
 
128
+ # The FALSE pseudo literal.
110
129
  def self.false
111
- Arel::Nodes::Equality.new(1,0)
130
+ Arel::Nodes::Equality.new(1, 0)
131
+ end
132
+
133
+ # The NULL literal.
134
+ def self.null
135
+ Arel::Nodes.build_quoted(nil)
112
136
  end
113
137
 
114
138
  def self.tuple *v
115
- tmp = Arel::Nodes::Grouping.new(nil)
116
- Arel::Nodes::Grouping.new(v.map{|e| tmp.convert_to_node(e)})
139
+ tmp = Arel.grouping(nil)
140
+ Arel.grouping v.map{|e| tmp.convert_to_node(e)}
117
141
  end
118
142
  end
119
143
 
@@ -123,6 +147,7 @@ class Arel::Attributes::Attribute
123
147
  end
124
148
 
125
149
  class Arel::Nodes::Function
150
+ include ArelExtensions::Aliases
126
151
  include ArelExtensions::Math
127
152
  include ArelExtensions::Comparators
128
153
  include ArelExtensions::DateDuration
@@ -189,6 +214,19 @@ end
189
214
  class Arel::SelectManager
190
215
  include ArelExtensions::SetFunctions
191
216
  include ArelExtensions::Nodes
217
+
218
+ def as table_name
219
+ Arel::Nodes::TableAlias.new(self, table_name)
220
+ end
221
+
222
+ # Install an alias, if present.
223
+ def xas table_name
224
+ if table_name.present?
225
+ as table_name
226
+ else
227
+ self
228
+ end
229
+ end
192
230
  end
193
231
 
194
232
  class Arel::Nodes::As
@@ -198,7 +236,11 @@ end
198
236
  class Arel::Table
199
237
  alias_method(:old_alias, :alias) rescue nil
200
238
  def alias(name = "#{self.name}_2")
201
- name.blank? ? self : Arel::Nodes::TableAlias.new(self,name)
239
+ if name.present?
240
+ Arel::Nodes::TableAlias.new(self, name)
241
+ else
242
+ self
243
+ end
202
244
  end
203
245
  end
204
246
 
@@ -6,6 +6,51 @@ require 'active_record'
6
6
 
7
7
  require 'support/fake_record'
8
8
 
9
+ def colored(color, msg)
10
+ ENV["TERM"] =~ /^xterm|-256color$/ ? "\x1b[#{color}m#{msg}\x1b[89m\x1b[0m" : "#{msg}"
11
+ end
12
+
13
+ YELLOW = "33"
14
+
15
+ def warn(msg)
16
+ $stderr.puts(colored(YELLOW, msg))
17
+ end
18
+
19
+ # Load gems specific to databases
20
+ # NOTE:
21
+ # It's strongly advised to test each database on its own. Loading multiple
22
+ # backend gems leads to undefined behavior according to tests; the backend
23
+ # might not recognize the correct DB visitor and will fallback to `ToSQL`
24
+ # and screw all tests.
25
+ #
26
+ # The issue also seems to be related to arel version: at some point, arel
27
+ # dropped its wide support for DBs and kept Postgres, MySQL and SQLite.
28
+ # Here, we're just trying to load the correct ones.
29
+ db_and_gem = if RUBY_ENGINE == 'jruby'
30
+ {
31
+ 'oracle' => 'activerecord-oracle_enhanced-adapter',
32
+ 'mssql' => 'activerecord-jdbcsqlserver-adapter'
33
+ }
34
+ else
35
+ {
36
+ 'oracle' => 'activerecord-oracle_enhanced-adapter',
37
+ 'mssql' => 'activerecord-sqlserver-adapter'
38
+ }
39
+ end
40
+
41
+ def load_lib(gem)
42
+ if gem && (RUBY_ENGINE == 'jruby' || Arel::VERSION.to_i > 9)
43
+ begin
44
+ Gem::Specification.find_by_name(gem)
45
+ require gem
46
+ rescue Gem::MissingSpecError
47
+ warn "Warning: failed to load gem #{gem}. Are you sure it's installed?"
48
+ end
49
+ end
50
+ end
51
+
52
+ load_lib(db_and_gem[ENV['DB']])
53
+
9
54
  require 'arel_extensions'
10
55
  Arel::Table.engine = FakeRecord::Base.new
11
56
 
data/test/database.yml CHANGED
@@ -9,23 +9,29 @@ jdbc-sqlite:
9
9
  mysql:
10
10
  adapter: mysql2
11
11
  database: arext_test
12
- username: travis
12
+ username: root
13
13
  host: 127.0.0.1
14
14
  port: 3306
15
15
  encoding: utf8
16
16
  jdbc-mysql:
17
17
  adapter: jdbcmysql
18
18
  database: arext_test
19
- username: travis
19
+ username: root
20
20
  encoding: utf8
21
21
  postgresql:
22
22
  adapter: postgresql
23
23
  database: arext_test
24
24
  username: postgres
25
+ password: secret
26
+ host: 127.0.0.1
27
+ port: 5432
25
28
  jdbc-postgresql:
26
29
  adapter: jdbcpostgresql
27
30
  database: arext_test
28
31
  username: postgres
32
+ password: secret
33
+ host: 127.0.0.1
34
+ port: 5432
29
35
  oracle:
30
36
  adapter: oracle_enhanced
31
37
  database: xe
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
@@ -105,7 +105,7 @@ module FakeRecord
105
105
  attr_reader :spec, :connection
106
106
 
107
107
  def initialize
108
- @spec = Spec.new(:adapter => 'america')
108
+ @spec = Spec.new({:adapter => 'america'})
109
109
  @connection = Connection.new
110
110
  @connection.visitor = Arel::Visitors::ToSql.new(connection)
111
111
  end
@@ -5,6 +5,27 @@ module ArelExtensions
5
5
  module VisitorToSql
6
6
  describe 'the to_sql visitor' do
7
7
  before do
8
+ if Arel::Table.engine.is_a?(ActiveRecord::Base)
9
+ puts "This is a hack."
10
+ # As a matter of fact, if the whole if-block is removed, the to_sql
11
+ # test become flaky.
12
+ #
13
+ # The first time `Arel::Table.engine` is called
14
+ # from `ArelExtenstions::column_of_via_arel_table(table_name, column_name)`
15
+ # in `lib/arel_extensions/helpers.rb`
16
+ # will almost always fail. It's important to note that when the test
17
+ # fails, it's always on 1 test case, and every subsequent test that
18
+ # calls to these methods passes.
19
+ #
20
+ # After investigation, it turned out that `Arel::Table.engine` will be
21
+ # of type `ActiveRecord::Base` instead of the expected `FakeRecord::Base`
22
+ # as set in this `before` block, in the `@conn` instance variable.
23
+ # Subsequent calls to `column_of_via_arel_table` will have
24
+ # `Arel::Table.engine` of the expected type.
25
+ #
26
+ # It is still unclear why the call in the condition of this if-block
27
+ # fixes this behavior.
28
+ end
8
29
  @conn = FakeRecord::Base.new
9
30
  Arel::Table.engine = @conn
10
31
  @visitor = Arel::Visitors::ToSql.new @conn.connection
@@ -282,16 +303,23 @@ module ArelExtensions
282
303
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END ILIKE 'value'}
283
304
  end
284
305
 
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}
306
+ it "should be possible to use as/xas on anything" do
307
+ {
308
+ @table[:name] => %{"users"."name" AS alias},
309
+ @table[:name].concat(' test') => %{CONCAT("users"."name", ' test') AS alias},
310
+ (@table[:name] + ' test') => %{CONCAT("users"."name", ' test') AS alias},
311
+ (@table[:age] + 42) => %{("users"."age" + 42) AS alias},
312
+ @table[:name].coalesce('') => %{COALESCE("users"."name", '') AS alias},
313
+ Arel::Nodes.build_quoted('test') => %{'test' AS alias},
314
+ @table.project(@table[:name]) => %{(SELECT "users"."name" FROM "users") "alias"},
315
+ @table[:name].when("smith").then("cool").else("uncool") => %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END AS alias},
316
+ }.each do |exp, res|
317
+ _(compile(exp.as('alias'))).must_be_like res
318
+ _(compile(exp.xas('alias'))).must_be_like res
319
+
320
+ res_no_alias = res.gsub(/\s*(?:AS alias|"alias")\s*\z/, '')
321
+ _(compile(exp.xas(nil))).must_be_like res_no_alias
322
+ end
295
323
  end
296
324
 
297
325
  it "should accept comparators on functions" do
@@ -373,7 +401,7 @@ module ArelExtensions
373
401
  end
374
402
 
375
403
  it "should respecting Grouping" do
376
- g = ->(*v) { Arel::Nodes::Grouping.new(v) }
404
+ g = ->(*v) { Arel.grouping(v) }
377
405
  _(compile(g[@table[:id], @table[:age]].in [g[1, 42]]))
378
406
  .must_be_like %{("users"."id", "users"."age") IN ((1, 42))}
379
407
  _(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
@@ -29,7 +33,7 @@ module ArelExtensions
29
33
  t.column :name, :string
30
34
  t.column :comments, :text
31
35
  t.column :created_at, :date
32
- t.column :updated_at, :datetime
36
+ t.column :updated_at, :datetime, precision: nil
33
37
  t.column :duration, :time
34
38
  t.column :other, :string
35
39
  t.column :score, :decimal, :precision => 20, :scale => 10
@@ -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,9 +368,70 @@ 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%%'))
373
+
374
+ # The following tests will ensure proper conversion of timestamps to
375
+ # requested timezones.
376
+ #
377
+ # The names of the timezones is highly dependant on the underlying
378
+ # operating system, and this is why we need to handle each database
379
+ # separately: the images we're using to test these databases are
380
+ # different. So don't rely on the provided examples. Your setup is your
381
+ # reference.
382
+ #
383
+ # One could always have portable code if s/he uses standard
384
+ # abbreviations, like:
385
+ #
386
+ # 1. CET => Central European Time
387
+ # 2. CEST => Central European Summer Time
388
+ #
389
+ # Which implies that the caller should handle daylight saving detection.
390
+ # In fact, CET will handle daylight saving in MySQL but not Postgres.
391
+ #
392
+ # It looks like the posix convention is supported by mysql and
393
+ # postgresql, e.g.:
394
+ #
395
+ # posix/Europe/Paris
396
+ # posix/America/Nipigon
397
+ #
398
+ # so it looks like a more reliably portable way of specifying it.
399
+ time_zones = {
400
+ 'mssql' => {
401
+ 'utc' => 'UTC',
402
+ 'sao_paulo' => 'Argentina Standard Time',
403
+ 'tahiti' => 'Hawaiian Standard Time',
404
+ 'paris' => 'Central European Standard Time'
405
+ },
406
+ 'mysql' => {
407
+ 'utc' => 'UTC',
408
+ 'sao_paulo' => 'America/Sao_Paulo',
409
+ 'tahiti' => 'Pacific/Tahiti',
410
+ 'paris' => 'Europe/Paris'
411
+ },
412
+ 'oracle' => {
413
+ 'utc' => 'UTC',
414
+ 'sao_paulo' => 'America/Sao_Paulo',
415
+ 'tahiti' => 'Pacific/Tahiti',
416
+ 'paris' => 'Europe/Paris'
417
+ },
418
+ 'postgresql' => {
419
+ 'utc' => 'UTC',
420
+ 'sao_paulo' => 'America/Sao Paulo (-03)',
421
+ 'tahiti' => 'Pacific/Tahiti (-10)',
422
+ 'paris' => 'Europe/Paris'
423
+ },
424
+ }
425
+
426
+ tz = time_zones[ENV['DB']]
427
+ skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if tz.nil?
428
+ assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['utc']))
429
+ assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['sao_paulo']))
430
+ assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['tahiti']))
431
+
432
+ # Winter/Summer time
433
+ assert_equal '2022/02/01 11:42:00', t(@lucas, Arel::Nodes.build_quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
434
+ assert_equal '2022/08/01 12:42:00', t(@lucas, Arel::Nodes.build_quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
364
435
  end
365
436
 
366
437
  def test_coalesce
@@ -500,7 +571,8 @@ module ArelExtensions
500
571
  assert_equal Time, t(@lucas,@updated_at.cast(:string).cast(:datetime)).class
501
572
  assert_equal Time, t(@lucas,@updated_at.cast(:time)).class
502
573
 
503
- assert_equal "2014-03-03 12:42:00", t(@lucas,@updated_at.cast(:string)) unless @env_db == 'mssql' # locale dependent
574
+ # mysql adapter in rails7 adds some infos we just squeeze here
575
+ assert_equal "2014-03-03 12:42:00", t(@lucas,@updated_at.cast(:string)).split('.').first unless @env_db == 'mssql' # locale dependent
504
576
  assert_equal Date.parse("2014-03-03"), t(@lucas,Arel::Nodes.build_quoted('2014-03-03').cast(:date))
505
577
  assert_equal Date.parse("5014-03-03"), t(@lucas,(@age.cast(:string) + '014-03-03').cast(:date))
506
578
  assert_equal Time.parse("2014-03-03 12:42:00 UTC"), t(@lucas,@updated_at.cast(:string).cast(:datetime))
@@ -515,7 +587,7 @@ module ArelExtensions
515
587
  # puts @age.is_null.inspect
516
588
  # puts @age.is_null.to_sql
517
589
  # puts @age=='34'
518
- assert_equal "Test", User.select(@name).where(@age.is_null.to_sql).first.name
590
+ assert_equal "Test", User.select(@name).where(@age.is_null).first.name
519
591
  end
520
592
 
521
593
  def test_math_plus
@@ -663,6 +735,7 @@ module ArelExtensions
663
735
  end
664
736
 
665
737
  def test_subquery_with_order
738
+ skip if ['mssql'].include?(@env_db) && Arel::VERSION.to_i < 10
666
739
  assert_equal 9, User.where(:name => User.select(:name).order(:name)).count
667
740
  assert_equal 9, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
668
741
  if !['mysql'].include?(@env_db) # MySql can't have limit in IN subquery
@@ -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.25".freeze
2
+ VERSION = "1.3.1".freeze
3
3
  end
data/version_v2.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = "2.0.22".freeze
2
+ VERSION = "2.1.1".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.0.22
4
+ version: 2.1.1
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: 2021-04-21 00:00:00.000000000 Z
13
+ date: 2022-03-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -44,16 +44,16 @@ dependencies:
44
44
  name: rdoc
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - "~>"
47
+ - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: '4.0'
49
+ version: 6.3.1
50
50
  type: :development
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - "~>"
54
+ - - ">="
55
55
  - !ruby/object:Gem::Version
56
- version: '4.0'
56
+ version: 6.3.1
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: rake
59
59
  requirement: !ruby/object:Gem::Requirement
@@ -97,7 +97,6 @@ files:
97
97
  - Rakefile
98
98
  - SQL_Challenges.md
99
99
  - TODO
100
- - appveyor.yml
101
100
  - arel_extensions.gemspec
102
101
  - functions.html
103
102
  - gemfiles/rails3.gemfile
@@ -107,6 +106,7 @@ files:
107
106
  - gemfiles/rails5_2.gemfile
108
107
  - gemfiles/rails6.gemfile
109
108
  - gemfiles/rails6_1.gemfile
109
+ - gemfiles/rails7.gemfile
110
110
  - gemspecs/arel_extensions-v1.gemspec
111
111
  - gemspecs/arel_extensions-v2.gemspec
112
112
  - generate_gems.sh
@@ -116,11 +116,13 @@ files:
116
116
  - init/postgresql.sql
117
117
  - init/sqlite.sql
118
118
  - lib/arel_extensions.rb
119
+ - lib/arel_extensions/aliases.rb
119
120
  - lib/arel_extensions/attributes.rb
120
121
  - lib/arel_extensions/boolean_functions.rb
121
122
  - lib/arel_extensions/common_sql_functions.rb
122
123
  - lib/arel_extensions/comparators.rb
123
124
  - lib/arel_extensions/date_duration.rb
125
+ - lib/arel_extensions/helpers.rb
124
126
  - lib/arel_extensions/insert_manager.rb
125
127
  - lib/arel_extensions/math.rb
126
128
  - lib/arel_extensions/math_functions.rb
@@ -222,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
224
  - !ruby/object:Gem::Version
223
225
  version: '0'
224
226
  requirements: []
225
- rubygems_version: 3.1.2
227
+ rubygems_version: 3.2.3
226
228
  signing_key:
227
229
  specification_version: 4
228
230
  summary: Extending Arel