arel-extensions 6.0.0.4 → 6.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08c6ce3898d57f105c59837161e36e1fe45f25afd4daa95d54916bef1c3782e5'
4
- data.tar.gz: 1f2efc0c80e2b25c826421126eb8d963a7244b1c386a7a0f871b46fcad701c11
3
+ metadata.gz: 6499ad3b57ef7119b545163cecc1972913c494d57bbfd19c81aecbbf74219880
4
+ data.tar.gz: 576fb2e56d087957430ff9e8cc5ee3dc968c2f17ba3d2c617a4eae2f6664f340
5
5
  SHA512:
6
- metadata.gz: d5610a339bd005e10ef756715bf25b0cc96dc471e6fec233a8f9735e6c4bb05f50425aaf0f465b6d4e57c0320949ed80a6e93d46b399e1975a4753185112fac3
7
- data.tar.gz: a5fde1fd877f44e52bde43595d4eb1237742f85ea338ad1a00597d075c5d0f30320bac95b41d5b58bf1460784035d51f14728702e22dd4cc401293137b28b1fb
6
+ metadata.gz: df8347481c7c0d86903d7f0fe35850da0ac725325ab18f11191f6c04455d88515cd47306ab1fb972f5ca2e8a49e678cbfd242c12a0850575a5cdbde95bb41a9b
7
+ data.tar.gz: 52c2e805c1758594478b229c421ba301571c82d715be1904f8fd00359ab7b399919d2d6f74c8548078ad141c41a7bc687d7d311b33f79ac171ca38f95859623f
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  .DS_Store
2
2
  *.gem
3
+ Gemfile.lock
@@ -1,4 +1,4 @@
1
- dist: xenial
1
+ dist: bionic
2
2
  language: ruby
3
3
  sudo: false
4
4
 
@@ -8,37 +8,60 @@ cache:
8
8
  - /home/travis/.rvm/gems
9
9
 
10
10
  rvm:
11
- - 2.5
12
- - 2.6
11
+ - 2.7
13
12
 
14
13
  env:
15
14
  matrix:
16
- - RAILS_VERSION=v6.0.0.rc1 GEM=activerecord:mysql2
17
- - RAILS_VERSION=v6.0.0.rc1 GEM=activerecord:sqlite3
18
- - RAILS_VERSION=v6.0.0.rc1 GEM=activerecord:postgresql
15
+ - RAILS_VERSION=v6.1.0 TASK='db:mysql:rebuild mysql2:test'
16
+ - RAILS_VERSION=v6.1.0 TASK='db:mysql:rebuild mysql2:isolated_test'
17
+ - RAILS_VERSION=v6.1.0 TASK='db:postgresql:rebuild postgresql:test'
18
+ - RAILS_VERSION=v6.1.0 TASK='db:postgresql:rebuild postgresql:isolated_test'
19
+ - RAILS_VERSION=v6.1.0 TASK='sqlite3:test'
20
+ - RAILS_VERSION=v6.1.0 TASK='sqlite3:isolated_test'
21
+ - RAILS_VERSION=v6.1.0 TASK='sqlite3_mem:test'
19
22
 
20
23
  services:
21
24
  - mysql
22
25
  addons:
23
- postgresql: "10"
26
+ postgresql: "13"
27
+ apt:
28
+ packages:
29
+ - postgresql-13
30
+ - postgresql-client-13
24
31
 
25
32
  before_install:
33
+ - sudo sed -i 's/port = 5433/port = 5432/' /etc/postgresql/13/main/postgresql.conf
34
+ - sudo cp /etc/postgresql/{9.3,13}/main/pg_hba.conf
35
+ - sudo pg_ctlcluster 13 main restart
26
36
  - unset BUNDLE_GEMFILE
27
37
  - gem update --system
28
38
  - gem update bundler
39
+ - gem install bundler --version 1.17.3
40
+ - mysql -e "create user rails@localhost;"
41
+ - mysql -e "grant all privileges on activerecord_unittest.* to rails@localhost;"
42
+ - mysql -e "grant all privileges on activerecord_unittest2.* to rails@localhost;"
43
+ - mysql -e "grant all privileges on inexistent_activerecord_unittest.* to rails@localhost;"
44
+ - mysql -e "create database activerecord_unittest default character set utf8mb4;"
45
+ - mysql -e "create database activerecord_unittest2 default character set utf8mb4;"
29
46
 
30
47
  install:
31
- - git clone https://github.com/rails/rails.git ~/build/rails
48
+ - git clone --branch $RAILS_VERSION https://github.com/rails/rails.git ~/build/rails
49
+
50
+ before_script:
51
+ - sed -i "s/t.warning = true/t.warning = false/g" Rakefile
32
52
  - pushd ~/build/rails
33
- - git checkout $RAILS_VERSION
53
+ - git status
34
54
  - sed -i "s/Gem.ruby, '-w'/Gem.ruby, '-w0'/" ~/build/rails/activerecord/Rakefile
35
55
  - sed -i "s/t.warning = true/t.warning = false/g" ~/build/rails/activerecord/Rakefile
36
56
  - sed -i "/require 'support\/connection'/a \$LOAD_PATH.unshift\(File.expand_path\('~\/build\/malomalo\/arel-extensions\/lib'\)\)\nrequire 'arel/extensions'" ~/build/rails/activerecord/test/cases/helper.rb
37
57
  - "sed -i \"/group :db do/a gem 'arel-extensions', require: 'arel/extensions', path: File.expand_path\\('~\\/build\\/malomalo\\/arel-extensions'\\)\" ~/build/rails/Gemfile"
38
58
  - sed -i "/rb-inotify/d" ~/build/rails/Gemfile
39
59
  - cat ~/build/rails/Gemfile
40
- - bundle install --jobs=3 --retry=3
60
+ - rm ~/build/rails/Gemfile.lock
61
+ - bundle update --jobs=3 --retry=3
41
62
  - popd
63
+ - bundle install --jobs=3 --retry=3
42
64
 
43
65
  script:
44
- - cd ~/build/rails && ci/travis.rb
66
+ - bundle exec rake test
67
+ - cd ~/build/rails/activerecord && bundle exec rake $TASK
@@ -1,6 +1,8 @@
1
+ require File.expand_path("../lib/arel/extensions/version", __FILE__)
2
+
1
3
  Gem::Specification.new do |gem|
2
4
  gem.name = 'arel-extensions'
3
- gem.version = '6.0.0.4'
5
+ gem.version = Arel::Extensions::VERSION
4
6
  gem.authors = ["Jon Bracy"]
5
7
  gem.email = ["jonbracy@gmail.com"]
6
8
  gem.summary = %q{Adds support for missing SQL operators and functions to Arel}
@@ -11,13 +13,16 @@ Gem::Specification.new do |gem|
11
13
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
12
14
  gem.require_paths = ["lib"]
13
15
 
14
- gem.add_dependency 'activerecord', '>= 6.0.0.rc1'
16
+ gem.add_dependency 'activerecord', '>= 6.1.0'
15
17
 
16
18
  gem.add_development_dependency "bundler"
19
+ gem.add_development_dependency "byebug"
17
20
  gem.add_development_dependency "rake"
18
21
  gem.add_development_dependency 'minitest'
19
22
  gem.add_development_dependency 'minitest-reporters'
23
+ gem.add_development_dependency "sunstone", '>= 6.1.0.rc1'
24
+ gem.add_development_dependency "webmock"
20
25
  gem.add_development_dependency 'pg'
21
26
  gem.add_development_dependency 'rgeo'
22
-
27
+
23
28
  end
@@ -0,0 +1,14 @@
1
+ module Arel
2
+ module Nodes
3
+ class Ascending < Ordering
4
+
5
+ attr_accessor :nulls
6
+
7
+ def initialize expr, nulls=nil
8
+ super(expr)
9
+ @nulls = nulls
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ module Arel
2
+ module Nodes
3
+ class Descending < Ordering
4
+
5
+ attr_accessor :nulls
6
+
7
+ def initialize expr, nulls=nil
8
+ super(expr)
9
+ @nulls = nulls
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # Ordering with :nulls_last, :nulls_first options
2
+ module Arel
3
+ module OrderPredications
4
+
5
+ def asc(nulls=nil)
6
+ Nodes::Ascending.new self, nulls
7
+ end
8
+
9
+ def desc(nulls=nil)
10
+ Nodes::Descending.new self, nulls
11
+ end
12
+
13
+ end
14
+ end
@@ -1,24 +1,14 @@
1
1
  module Arel
2
2
  module ArrayPredications
3
-
4
- # Used by both JSON and ARRAY so it doesn't try to cast to array
5
- def contains(value)
6
- Arel::Nodes::Contains.new(self, value)
7
- end
8
-
3
+
9
4
  # Used by both JSON and ARRAY so it doesn't try to cast to array
10
5
  def contained_by(value)
11
6
  Arel::Nodes::ContainedBy.new(self, value)
12
7
  end
13
-
8
+
14
9
  def excludes(value)
15
10
  Arel::Nodes::Excludes.new(self, value)
16
11
  end
17
-
18
- def overlaps(*values)
19
- values = values[0] if values.size == 1 && values[0].is_a?(Array)
20
- Arel::Nodes::Overlaps.new(self, values)
21
- end
22
-
12
+
23
13
  end
24
- end
14
+ end
@@ -1,14 +1,17 @@
1
1
  require "arel"
2
2
  require File.expand_path('../nodes/hex_encoded_binary', __FILE__)
3
3
 
4
- require File.expand_path('../nodes/overlaps', __FILE__)
5
- require File.expand_path('../nodes/contains', __FILE__)
6
4
  require File.expand_path('../nodes/within', __FILE__)
7
5
  require File.expand_path('../nodes/excludes', __FILE__)
8
6
  require File.expand_path('../nodes/contained_by', __FILE__)
9
7
  require File.expand_path('../array_predications', __FILE__)
10
8
  Arel::Attributes::Attribute.include(Arel::ArrayPredications)
11
9
 
10
+ require File.expand_path('../nodes/random', __FILE__)
11
+ require File.expand_path(File.join(__FILE__, '../../../ext/arel/nodes/ascending'))
12
+ require File.expand_path(File.join(__FILE__, '../../../ext/arel/nodes/descending'))
13
+ require File.expand_path(File.join(__FILE__, '../../../ext/arel/order_predications'))
14
+
12
15
 
13
16
  require File.expand_path('../attributes/key', __FILE__)
14
17
  require File.expand_path('../attributes/cast', __FILE__)
@@ -26,6 +29,7 @@ require File.expand_path('../nodes/ts_rank_cd', __FILE__)
26
29
  require File.expand_path('../ts_predications', __FILE__)
27
30
  Arel::Attributes::Attribute.include(Arel::TSPredications)
28
31
 
32
+ require File.expand_path('../nodes/relation', __FILE__)
29
33
 
30
34
  require File.expand_path('../gis_predications', __FILE__)
31
35
  Arel::Attributes::Attribute.include(Arel::GISPredications)
@@ -38,4 +42,8 @@ end
38
42
 
39
43
  if defined?(Arel::Visitors::Sunstone)
40
44
  require File.expand_path('../visitors/sunstone_extensions', __FILE__)
45
+ end
46
+
47
+ if defined?(Arel::Visitors::ToSql)
48
+ require File.expand_path('../visitors/to_sql_extensions', __FILE__)
41
49
  end
@@ -0,0 +1,5 @@
1
+ module Arel
2
+ module Extensions
3
+ VERSION = '6.1.0.rc1'
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module Arel
2
+ module Nodes
3
+ class RandomOrdering < Arel::Nodes::Node
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ module Arel
2
+ module Attributes
3
+ class Relation < Attribute
4
+
5
+ attr_accessor :collection, :for_write
6
+
7
+ def initialize(relation, name, collection = false, for_write=false)
8
+ self[:relation] = relation
9
+ self[:name] = name
10
+ @collection = collection
11
+ @for_write = for_write
12
+ end
13
+
14
+ def able_to_type_cast?
15
+ false
16
+ end
17
+
18
+ def table_name
19
+ nil
20
+ end
21
+
22
+ def eql? other
23
+ self.class == other.class &&
24
+ self.relation == other.relation &&
25
+ self.name == other.name &&
26
+ self.collection == other.collection
27
+ end
28
+
29
+ def type_cast_for_database(value)
30
+ relation.type_cast_for_database(value)
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -2,11 +2,12 @@ module Arel
2
2
  module Nodes
3
3
  class TSRankCD < Arel::Nodes::Node
4
4
 
5
- attr_reader :tsvector, :tsquery
5
+ attr_reader :tsvector, :tsquery, :normalization
6
6
 
7
- def initialize(tsvector, tsquery)
7
+ def initialize(tsvector, tsquery, normalization=nil)
8
8
  @tsvector = tsvector
9
9
  @tsquery = tsquery
10
+ @normalization = normalization
10
11
  end
11
12
 
12
13
  end
@@ -2,11 +2,11 @@ module Arel
2
2
  module TSPredications
3
3
 
4
4
  def ts_query(expression, language=nil)
5
- vector = Arel::Nodes::TSVector.new(self, language)
6
- query = Arel::Nodes::TSQuery.new(expression, language)
5
+ vector = Arel::Nodes::TSVector.new(self, language: language)
6
+ query = Arel::Nodes::TSQuery.new(expression, language: language)
7
7
 
8
8
  Arel::Nodes::TSMatch.new(vector, query)
9
9
  end
10
10
 
11
11
  end
12
- end
12
+ end
@@ -8,11 +8,24 @@ module Arel
8
8
  super
9
9
  end
10
10
 
11
- def visit_Arel_Nodes_Contains o, collector
12
- visit o.left, collector
13
- collector << ' @> '
14
- collector << quote(o.left.type_cast_for_database(o.right))
15
- collector
11
+ def visit_Arel_Nodes_Ascending o, collector
12
+ case o.nulls
13
+ when :nulls_first then visit(o.expr, collector) << ' ASC NULLS FIRST'
14
+ when :nulls_last then visit(o.expr, collector) << ' ASC NULLS LAST'
15
+ else visit(o.expr, collector) << ' ASC'
16
+ end
17
+ end
18
+
19
+ def visit_Arel_Nodes_Descending o, collector
20
+ case o.nulls
21
+ when :nulls_first then visit(o.expr, collector) << ' DESC NULLS FIRST'
22
+ when :nulls_last then visit(o.expr, collector) << ' DESC NULLS LAST'
23
+ else visit(o.expr, collector) << ' DESC'
24
+ end
25
+ end
26
+
27
+ def visit_Arel_Nodes_RandomOrdering o, collector
28
+ collector << "RANDOM()"
16
29
  end
17
30
 
18
31
  def visit_Arel_Nodes_ContainedBy o, collector
@@ -31,13 +44,6 @@ module Arel
31
44
  collector
32
45
  end
33
46
 
34
- def visit_Arel_Nodes_Overlaps o, collector
35
- visit o.left, collector
36
- collector << ' && '
37
- collector << quote(o.left.type_cast_for_database(o.right))
38
- collector
39
- end
40
-
41
47
  def visit_Arel_Attributes_Key(o, collector, last_key = true)
42
48
  if o.relation.is_a?(Arel::Attributes::Key)
43
49
  visit_Arel_Attributes_Key(o.relation, collector, false)
@@ -133,6 +139,10 @@ module Arel
133
139
  visit(o.tsvector, collector)
134
140
  collector << ', '
135
141
  visit(o.tsquery, collector)
142
+ if o.normalization
143
+ collector << ', '
144
+ visit(o.normalization, collector)
145
+ end
136
146
  collector << ')'
137
147
  collector
138
148
  end
@@ -3,12 +3,64 @@ module Arel
3
3
  class Sunstone
4
4
  private
5
5
 
6
+ def visit_Arel_Nodes_Ascending o, collector
7
+ hash = visit(o.expr, collector)
8
+
9
+ value = case o.nulls
10
+ when :nulls_first
11
+ {asc: :nulls_first}
12
+ when :nulls_last
13
+ {asc: :nulls_last}
14
+ else
15
+ :asc
16
+ end
17
+
18
+ if hash.is_a?(Hash)
19
+ add_to_bottom_of_hash_or_array(hash, value)
20
+ else
21
+ hash = { hash => value }
22
+ end
23
+
24
+ hash
25
+ end
26
+
27
+ def visit_Arel_Nodes_Descending o, collector
28
+ hash = visit(o.expr, collector)
29
+
30
+ value = case o.nulls
31
+ when :nulls_first
32
+ {desc: :nulls_first}
33
+ when :nulls_last
34
+ {desc: :nulls_last}
35
+ else
36
+ :desc
37
+ end
38
+
39
+ if hash.is_a?(Hash)
40
+ add_to_bottom_of_hash_or_array(hash, value)
41
+ else
42
+ hash = { hash => value }
43
+ end
44
+
45
+ hash
46
+ end
47
+
48
+ def visit_Arel_Nodes_RandomOrdering o, collector
49
+ :random
50
+ end
51
+
6
52
  def visit_Hash o, collector
7
- value = {}
53
+ rvalue = {}
8
54
  o.each do |key, value|
9
- value[visit(key, collector)] = visit(value, collector)
55
+ rvalue[visit(key, collector)] = visit(value, collector)
10
56
  end
11
- value
57
+ rvalue
58
+ end
59
+
60
+ alias :visit_String :literal
61
+
62
+ def visit_Symbol o, collector
63
+ o.to_s
12
64
  end
13
65
 
14
66
  def visit_Arel_Nodes_Contains o, collector
@@ -0,0 +1,11 @@
1
+ module Arel
2
+ module Visitors
3
+ class ToSql
4
+
5
+ def visit_Arel_Attributes_Relation(o, collector)
6
+ visit(o.relation, collector)
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -1,16 +1,14 @@
1
- task = ActiveRecord::Tasks::PostgreSQLDatabaseTasks.new({
2
- 'adapter' => 'postgresql',
3
- 'database' => "arel-extensions-test"
4
- })
5
- task.drop
6
- task.create
7
-
8
1
  ActiveRecord::Base.establish_connection({
9
2
  adapter: "postgresql",
10
3
  database: "arel-extensions-test",
11
4
  encoding: "utf8"
12
5
  })
13
6
 
7
+ db_config = ActiveRecord::Base.connection_db_config
8
+ task = ActiveRecord::Tasks::PostgreSQLDatabaseTasks.new(db_config)
9
+ task.drop
10
+ task.create
11
+
14
12
  ActiveRecord::Migration.suppress_messages do
15
13
  ActiveRecord::Schema.define do
16
14
 
@@ -18,7 +16,7 @@ ActiveRecord::Migration.suppress_messages do
18
16
  t.integer "name"
19
17
  t.integer "property_id"
20
18
  end
21
-
19
+
22
20
  create_table "properties", force: :cascade do |t|
23
21
  t.string "name", limit: 255
24
22
  t.tsvector 'vector_col'
@@ -29,13 +27,23 @@ ActiveRecord::Migration.suppress_messages do
29
27
  end
30
28
 
31
29
  class Address < ActiveRecord::Base
32
-
33
30
  belongs_to :property
34
-
35
31
  end
36
32
 
37
33
  class Property < ActiveRecord::Base
38
-
39
34
  has_many :addresses
35
+ end
36
+
37
+ class SunstoneRecord < ActiveRecord::Base
38
+ self.abstract_class = true
39
+ end
40
+
41
+ class SunstoneAddress < SunstoneRecord
42
+ belongs_to :property, class_name: 'SunstoneProperty'
43
+ end
44
+
45
+ class SunstoneProperty < SunstoneRecord
46
+ has_many :addresses, class_name: 'SunstoneAddress'
47
+ end
40
48
 
41
- end
49
+ SunstoneRecord.establish_connection(adapter: 'sunstone', endpoint: 'http://example.com')
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ class OrderTest < ActiveSupport::TestCase
4
+
5
+ test '::order(column.asc)' do
6
+ assert_sql(<<~SQL, Property.order(Property.arel_table[:id].asc))
7
+ SELECT "properties".* FROM "properties" ORDER BY "properties"."id" ASC
8
+ SQL
9
+ end
10
+
11
+ test '::order(column1.asc, column2.asc)' do
12
+ assert_sql(<<~SQL, Property.order(Property.arel_table[:id].asc, Property.arel_table[:name].asc))
13
+ SELECT "properties".* FROM "properties" ORDER BY "properties"."id" ASC, "properties"."name" ASC
14
+ SQL
15
+ end
16
+
17
+ test '::order(column.desc)' do
18
+ assert_sql(<<~SQL, Property.order(Property.arel_table[:id].desc))
19
+ SELECT "properties".* FROM "properties" ORDER BY "properties"."id" DESC
20
+ SQL
21
+ end
22
+
23
+ test '::order(column.asc(:nulls_first))' do
24
+ assert_sql(<<~SQL, Property.order(Property.arel_table[:id].asc(:nulls_first)))
25
+ SELECT "properties".* FROM "properties" ORDER BY "properties"."id" ASC NULLS FIRST
26
+ SQL
27
+ end
28
+
29
+ test '::order(column.asc(:nulls_last))' do
30
+ assert_sql(<<~SQL, Property.order(Property.arel_table[:id].asc(:nulls_last)))
31
+ SELECT "properties".* FROM "properties" ORDER BY "properties"."id" ASC NULLS LAST
32
+ SQL
33
+ end
34
+
35
+ test '::order(column.desc(:nulls_first))' do
36
+ assert_sql(<<~SQL, Property.order(Property.arel_table[:id].desc(:nulls_first)))
37
+ SELECT "properties".* FROM "properties" ORDER BY "properties"."id" DESC NULLS FIRST
38
+ SQL
39
+ end
40
+
41
+ test '::order(column.desc(:nulls_last))' do
42
+ assert_sql(<<~SQL, Property.order(Property.arel_table[:id].desc(:nulls_last)))
43
+ SELECT "properties".* FROM "properties" ORDER BY "properties"."id" DESC NULLS LAST
44
+ SQL
45
+ end
46
+
47
+ end
@@ -27,8 +27,11 @@ class SunstoneTest < ActiveSupport::TestCase
27
27
  # end
28
28
 
29
29
  test "::filter json_column: {contains: JSON_HASH}" do
30
- query = Property.where(Property.arel_attribute('metadata').contains({json: 'string'}))
31
- assert_equal '', query.to_sar.path
30
+ query = SunstoneProperty.where(SunstoneProperty.arel_table['metadata'].contains({json: 'string'}))
31
+ assert_sar(query, 'GET', '/sunstone_properties', {
32
+ where: {metadata: {contains: { json: 'string' }}}
33
+ })
34
+
32
35
  # query = Property.where(metadata: {contains: {json: 'string'}})
33
36
  # assert_equal(<<-SQL.strip.gsub(/\s+/, ' '), query.to_sql.strip)
34
37
  # SELECT "properties".*
@@ -94,5 +97,53 @@ class SunstoneTest < ActiveSupport::TestCase
94
97
  # SQL
95
98
  # end
96
99
 
100
+ test '::order(column.asc)' do
101
+ query = SunstoneProperty.order(SunstoneProperty.arel_table[:id].asc)
102
+ assert_sar(query, 'GET', '/sunstone_properties', {
103
+ order: [{ id: :asc }]
104
+ })
105
+ end
106
+
107
+ test '::order(column1.asc, column2.asc)' do
108
+ query = SunstoneProperty.order(SunstoneProperty.arel_table[:id].asc, SunstoneProperty.arel_table[:name].asc)
109
+ assert_sar(query, 'GET', '/sunstone_properties', {
110
+ order: [{ id: :asc }, { name: :asc }]
111
+ })
112
+ end
113
+
114
+ test '::order(column.desc)' do
115
+ query = SunstoneProperty.order(SunstoneProperty.arel_table[:id].desc)
116
+ assert_sar(query, 'GET', '/sunstone_properties', {
117
+ order: [{ id: :desc }]
118
+ })
119
+ end
120
+
121
+ test '::order(column.asc(:nulls_first))' do
122
+ query = SunstoneProperty.order(SunstoneProperty.arel_table[:id].asc(:nulls_first))
123
+ assert_sar(query, 'GET', '/sunstone_properties', {
124
+ order: [{ id: { asc: :nulls_first } }]
125
+ })
126
+ end
127
+
128
+ test '::order(column.asc(:nulls_last))' do
129
+ query = SunstoneProperty.order(SunstoneProperty.arel_table[:id].asc(:nulls_last))
130
+ assert_sar(query, 'GET', '/sunstone_properties', {
131
+ order: [{ id: { asc: :nulls_last } }]
132
+ })
133
+ end
134
+
135
+ test '::order(column.desc(:nulls_first))' do
136
+ query = SunstoneProperty.order(SunstoneProperty.arel_table[:id].desc(:nulls_first))
137
+ assert_sar(query, 'GET', '/sunstone_properties', {
138
+ order: [{ id: { desc: :nulls_first } }]
139
+ })
140
+ end
141
+
142
+ test '::order(column.desc(:nulls_last))' do
143
+ query = SunstoneProperty.order(SunstoneProperty.arel_table[:id].desc(:nulls_last))
144
+ assert_sar(query, 'GET', '/sunstone_properties', {
145
+ order: [{ id: { desc: :nulls_last } }]
146
+ })
147
+ end
97
148
 
98
149
  end
@@ -12,11 +12,13 @@ require 'rgeo'
12
12
  require "minitest/autorun"
13
13
  require 'minitest/unit'
14
14
  require 'minitest/reporters'
15
- # require 'webmock/minitest'
15
+ require 'webmock/minitest'
16
16
  # require 'mocha/minitest'
17
17
  require 'active_record'
18
+ require 'sunstone'
18
19
  require 'arel/extensions'
19
20
 
21
+
20
22
  # Setup the test db
21
23
  ActiveSupport.test_order = :random
22
24
  require File.expand_path('../database', __FILE__)
@@ -27,8 +29,8 @@ $debugging = false
27
29
 
28
30
  # File 'lib/active_support/testing/declarative.rb', somewhere in rails....
29
31
  class ActiveSupport::TestCase
30
- # include WebMock::API
31
-
32
+ include WebMock::API
33
+
32
34
  # File 'lib/active_support/testing/declarative.rb'
33
35
  def self.test(name, &block)
34
36
  test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
@@ -42,7 +44,7 @@ class ActiveSupport::TestCase
42
44
  end
43
45
  end
44
46
  end
45
-
47
+
46
48
  def webmock(method, path, query=nil)
47
49
  query = deep_transform_query(query) if query
48
50
 
@@ -55,6 +57,51 @@ class ActiveSupport::TestCase
55
57
  end
56
58
  end
57
59
 
60
+ def setup
61
+ sunstone_schema = {
62
+ addresses: {
63
+ columns: {
64
+ id: { type: :integer, primary_key: true, null: false, array: false },
65
+ name: { type: :string, primary_key: false, null: true, array: false },
66
+ property_id: { type: :integer, primary_key: false, null: true, array: false }
67
+ }
68
+ },
69
+ properties: {
70
+ columns: {
71
+ id: { type: :integer, primary_key: true, null: false, array: false },
72
+ name: { type: :string, primary_key: false, null: true, array: false },
73
+ metadata: { type: :json, primary_key: false, null: true, array: false }
74
+ }
75
+ }
76
+ }
77
+
78
+ req_stub = stub_request(:get, /^http:\/\/example.com/).with do |req|
79
+ case req.uri.path
80
+ when '/tables'
81
+ true
82
+ when /^\/\w+\/schema$/i
83
+ true
84
+ else
85
+ false
86
+ end
87
+ end
88
+
89
+ req_stub.to_return do |req|
90
+ case req.uri.path
91
+ when '/tables'
92
+ {
93
+ body: sunstone_schema.keys.to_json,
94
+ headers: { 'StandardAPI-Version' => '5.0.0.5' }
95
+ }
96
+ when /^\/(\w+)\/schema$/i
97
+ {
98
+ body: sunstone_schema[$1.to_sym].to_json,
99
+ headers: { 'StandardAPI-Version' => '5.0.0.5' }
100
+ }
101
+ end
102
+ end
103
+ end
104
+
58
105
  def debug
59
106
  ActiveRecord::Base.logger = Logger.new(STDOUT)
60
107
  $debugging = true
@@ -104,7 +151,7 @@ class ActiveSupport::TestCase
104
151
  unless ignore =~ sql
105
152
  if $debugging
106
153
  puts caller.select { |l| l.starts_with?(File.expand_path('../../lib', __FILE__)) }
107
- puts "\n\n"
154
+ puts "\n\n"
108
155
  end
109
156
  end
110
157
  self.class.log << sql unless ignore =~ sql
@@ -112,6 +159,37 @@ class ActiveSupport::TestCase
112
159
  end
113
160
  ActiveSupport::Notifications.subscribe('sql.active_record', SQLLogger.new)
114
161
 
162
+ def deep_transform_query(object)
163
+ case object
164
+ when Hash
165
+ object.each_with_object({}) do |(key, value), result|
166
+ result[key.to_s] = deep_transform_query(value)
167
+ end
168
+ when Array
169
+ object.map {|e| deep_transform_query(e) }
170
+ when Symbol
171
+ object.to_s
172
+ else
173
+ object
174
+ end
175
+ end
176
+
177
+ def assert_sar(query, method, path, query_params = {}, body = nil)
178
+ sar = query.to_sar
179
+
180
+ assert_equal method, sar.method
181
+ assert_equal path, sar.path.split('?').first
182
+ assert_equal deep_transform_query(query_params), MessagePack.unpack(CGI::unescape(sar.path.split('?').last))
183
+ if body.nil?
184
+ assert_nil sar.body
185
+ else
186
+ assert_equal body, sar.body
187
+ end
188
+ end
189
+
190
+ def assert_sql(expected, query)
191
+ assert_equal expected.strip, query.to_sql.strip.gsub(/\s+/, ' ')
192
+ end
115
193
  # test/unit backwards compatibility methods
116
194
  alias :assert_raise :assert_raises
117
195
  alias :assert_not_empty :refute_empty
@@ -127,5 +205,5 @@ class ActiveSupport::TestCase
127
205
  alias :assert_not_predicate :refute_predicate
128
206
  alias :assert_not_respond_to :refute_respond_to
129
207
  alias :assert_not_same :refute_same
130
-
131
- end
208
+
209
+ end
@@ -133,4 +133,19 @@ class TSTest < ActiveSupport::TestCase
133
133
  SQL
134
134
  end
135
135
 
136
+ test 'ts_rank_cd(tsvector, tsquery, normalization)' do
137
+ query = Property.where(
138
+ Arel::Nodes::TSRankCD.new(
139
+ Arel::Nodes::TSVector.new(Property.arel_table[:name]),
140
+ Arel::Nodes::TSQuery.new('query'),
141
+ 5
142
+ )
143
+ )
144
+
145
+ assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
146
+ SELECT "properties".* FROM "properties"
147
+ WHERE ts_rank_cd(to_tsvector("properties"."name"), to_tsquery('query'), 5)
148
+ SQL
149
+ end
150
+
136
151
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arel-extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0.4
4
+ version: 6.1.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Bracy
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-13 00:00:00.000000000 Z
11
+ date: 2020-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 6.0.0.rc1
19
+ version: 6.1.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 6.0.0.rc1
26
+ version: 6.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,34 @@ dependencies:
80
94
  - - ">="
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sunstone
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 6.1.0.rc1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 6.1.0.rc1
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
83
125
  - !ruby/object:Gem::Dependency
84
126
  name: pg
85
127
  requirement: !ruby/object:Gem::Requirement
@@ -108,7 +150,7 @@ dependencies:
108
150
  - - ">="
109
151
  - !ruby/object:Gem::Version
110
152
  version: '0'
111
- description:
153
+ description:
112
154
  email:
113
155
  - jonbracy@gmail.com
114
156
  executables: []
@@ -118,26 +160,29 @@ files:
118
160
  - ".gitignore"
119
161
  - ".travis.yml"
120
162
  - Gemfile
121
- - Gemfile.lock
122
163
  - LICENSE
123
164
  - README.md
124
165
  - Rakefile
125
166
  - arel-extensions.gemspec
167
+ - ext/arel/nodes/ascending.rb
168
+ - ext/arel/nodes/descending.rb
169
+ - ext/arel/order_predications.rb
126
170
  - lib/active_record/query_methods.rb
127
171
  - lib/arel/array_predications.rb
128
172
  - lib/arel/attributes/cast.rb
129
173
  - lib/arel/attributes/key.rb
130
174
  - lib/arel/extensions.rb
175
+ - lib/arel/extensions/version.rb
131
176
  - lib/arel/gis_predications.rb
132
177
  - lib/arel/json_predications.rb
133
178
  - lib/arel/nodes/contained_by.rb
134
- - lib/arel/nodes/contains.rb
135
179
  - lib/arel/nodes/excludes.rb
136
180
  - lib/arel/nodes/has_any_key.rb
137
181
  - lib/arel/nodes/has_key.rb
138
182
  - lib/arel/nodes/has_keys.rb
139
183
  - lib/arel/nodes/hex_encoded_binary.rb
140
- - lib/arel/nodes/overlaps.rb
184
+ - lib/arel/nodes/random.rb
185
+ - lib/arel/nodes/relation.rb
141
186
  - lib/arel/nodes/ts_match.rb
142
187
  - lib/arel/nodes/ts_query.rb
143
188
  - lib/arel/nodes/ts_rank.rb
@@ -147,7 +192,9 @@ files:
147
192
  - lib/arel/ts_predications.rb
148
193
  - lib/arel/visitors/postgresql_extensions.rb
149
194
  - lib/arel/visitors/sunstone_extensions.rb
195
+ - lib/arel/visitors/to_sql_extensions.rb
150
196
  - test/database.rb
197
+ - test/order_test.rb
151
198
  - test/sunstone_test.rb
152
199
  - test/test_helper.rb
153
200
  - test/ts_test.rb
@@ -155,7 +202,7 @@ homepage: https://github.com/malomalo/arel-extensions
155
202
  licenses:
156
203
  - MIT
157
204
  metadata: {}
158
- post_install_message:
205
+ post_install_message:
159
206
  rdoc_options: []
160
207
  require_paths:
161
208
  - lib
@@ -166,16 +213,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
166
213
  version: '0'
167
214
  required_rubygems_version: !ruby/object:Gem::Requirement
168
215
  requirements:
169
- - - ">="
216
+ - - ">"
170
217
  - !ruby/object:Gem::Version
171
- version: '0'
218
+ version: 1.3.1
172
219
  requirements: []
173
- rubygems_version: 3.0.3
174
- signing_key:
220
+ rubygems_version: 3.1.4
221
+ signing_key:
175
222
  specification_version: 4
176
223
  summary: Adds support for missing SQL operators and functions to Arel
177
224
  test_files:
178
225
  - test/database.rb
226
+ - test/order_test.rb
179
227
  - test/sunstone_test.rb
180
228
  - test/test_helper.rb
181
229
  - test/ts_test.rb
@@ -1,54 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- arel-extensions (6.0.0.2)
5
- activerecord (>= 6.0.0.rc1)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (6.0.0.rc2)
11
- activesupport (= 6.0.0.rc2)
12
- activerecord (6.0.0.rc2)
13
- activemodel (= 6.0.0.rc2)
14
- activesupport (= 6.0.0.rc2)
15
- activesupport (6.0.0.rc2)
16
- concurrent-ruby (~> 1.0, >= 1.0.2)
17
- i18n (>= 0.7, < 2)
18
- minitest (~> 5.1)
19
- tzinfo (~> 1.1)
20
- zeitwerk (~> 2.1, >= 2.1.8)
21
- ansi (1.5.0)
22
- builder (3.2.3)
23
- concurrent-ruby (1.1.5)
24
- i18n (1.6.0)
25
- concurrent-ruby (~> 1.0)
26
- minitest (5.11.3)
27
- minitest-reporters (1.3.5)
28
- ansi
29
- builder
30
- minitest (>= 5.0)
31
- ruby-progressbar
32
- pg (1.1.3)
33
- rake (12.3.1)
34
- rgeo (1.0.0)
35
- ruby-progressbar (1.10.0)
36
- thread_safe (0.3.6)
37
- tzinfo (1.2.5)
38
- thread_safe (~> 0.1)
39
- zeitwerk (2.1.9)
40
-
41
- PLATFORMS
42
- ruby
43
-
44
- DEPENDENCIES
45
- arel-extensions!
46
- bundler
47
- minitest
48
- minitest-reporters
49
- pg
50
- rake
51
- rgeo
52
-
53
- BUNDLED WITH
54
- 1.17.3
@@ -1,6 +0,0 @@
1
- module Arel
2
- module Nodes
3
- class Contains < Binary
4
- end
5
- end
6
- end
@@ -1,6 +0,0 @@
1
- module Arel
2
- module Nodes
3
- class Overlaps < Binary
4
- end
5
- end
6
- end