arel-extensions 8.0.2 → 9.0.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/README.md +83 -2
  4. data/ext/arel/nodes/ascending.rb +2 -0
  5. data/ext/arel/nodes/descending.rb +2 -0
  6. data/ext/arel/order_predications.rb +2 -0
  7. data/lib/active_record/query_methods.rb +33 -31
  8. data/lib/arel/array_predications.rb +2 -0
  9. data/lib/arel/attributes/cast.rb +2 -0
  10. data/lib/arel/attributes/key.rb +2 -0
  11. data/lib/arel/extensions/version.rb +3 -1
  12. data/lib/arel/extensions.rb +2 -0
  13. data/lib/arel/gis_predications.rb +2 -0
  14. data/lib/arel/json_predications.rb +2 -0
  15. data/lib/arel/nodes/binary_value.rb +2 -0
  16. data/lib/arel/nodes/contained_by.rb +2 -0
  17. data/lib/arel/nodes/excludes.rb +2 -0
  18. data/lib/arel/nodes/geometry.rb +2 -0
  19. data/lib/arel/nodes/has_any_key.rb +2 -0
  20. data/lib/arel/nodes/has_key.rb +2 -0
  21. data/lib/arel/nodes/has_keys.rb +2 -0
  22. data/lib/arel/nodes/hex_encoded_binary_value.rb +2 -0
  23. data/lib/arel/nodes/intersects.rb +2 -0
  24. data/lib/arel/nodes/random.rb +2 -0
  25. data/lib/arel/nodes/relation.rb +2 -0
  26. data/lib/arel/nodes/ts_match.rb +2 -0
  27. data/lib/arel/nodes/ts_query.rb +2 -0
  28. data/lib/arel/nodes/ts_rank.rb +2 -0
  29. data/lib/arel/nodes/ts_rank_cd.rb +2 -0
  30. data/lib/arel/nodes/ts_vector.rb +2 -0
  31. data/lib/arel/nodes/within.rb +2 -0
  32. data/lib/arel/ts_predications.rb +2 -0
  33. data/lib/arel/visitors/postgresql_extensions.rb +2 -0
  34. data/lib/arel/visitors/sunstone_extensions.rb +2 -0
  35. data/lib/arel/visitors/to_sql_extensions.rb +2 -0
  36. metadata +15 -45
  37. data/.github/workflows/ci.yml +0 -212
  38. data/.gitignore +0 -3
  39. data/Gemfile +0 -5
  40. data/Rakefile +0 -14
  41. data/arel-extensions.gemspec +0 -29
  42. data/test/binary_value_test.rb +0 -23
  43. data/test/database.rb +0 -51
  44. data/test/gis_test.rb +0 -23
  45. data/test/order_test.rb +0 -83
  46. data/test/sunstone_test.rb +0 -149
  47. data/test/test_helper.rb +0 -210
  48. data/test/ts_test.rb +0 -151
data/test/test_helper.rb DELETED
@@ -1,210 +0,0 @@
1
- # To make testing/debugging easier, test within this source tree versus an
2
- # installed gem
3
- $LOAD_PATH << File.expand_path('../lib', __FILE__)
4
-
5
- # require 'simplecov'
6
- # SimpleCov.start do
7
- # add_group 'lib', 'sunstone/lib'
8
- # add_group 'ext', 'sunstone/ext'
9
- # end
10
-
11
- require 'rgeo'
12
- require 'debug'
13
- require "minitest/autorun"
14
- require 'minitest/unit'
15
- require 'minitest/reporters'
16
- require 'webmock/minitest'
17
- # require 'mocha/minitest'
18
- require 'active_record'
19
- require 'sunstone'
20
- require 'arel/extensions'
21
- require 'activerecord-postgis-adapter'
22
-
23
- # Setup the test db
24
- ActiveSupport.test_order = :random
25
- require File.expand_path('../database', __FILE__)
26
-
27
- Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
28
-
29
- $debugging = false
30
-
31
- # File 'lib/active_support/testing/declarative.rb', somewhere in rails....
32
- class ActiveSupport::TestCase
33
- include WebMock::API
34
-
35
- # File 'lib/active_support/testing/declarative.rb'
36
- def self.test(name, &block)
37
- test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
38
- defined = method_defined? test_name
39
- raise "#{test_name} is already defined in #{self}" if defined
40
- if block_given?
41
- define_method(test_name, &block)
42
- else
43
- define_method(test_name) do
44
- skip "No implementation provided for #{name}"
45
- end
46
- end
47
- end
48
-
49
- def webmock(method, path, query=nil)
50
- query = deep_transform_query(query) if query
51
-
52
- stub_request(method, /^#{ActiveRecord::Base.connection.instance_variable_get(:@connection).url}/).with do |req|
53
- if query
54
- req&.uri&.path == path && req.uri.query && unpack(req.uri.query.sub(/=true$/, '')) == query
55
- else
56
- req&.uri&.path == path && req.uri.query.nil?
57
- end
58
- end
59
- end
60
-
61
- def setup
62
- sunstone_schema = {
63
- addresses: {
64
- columns: {
65
- id: { type: :integer, primary_key: true, null: false, array: false },
66
- name: { type: :string, primary_key: false, null: true, array: false },
67
- property_id: { type: :integer, primary_key: false, null: true, array: false }
68
- }
69
- },
70
- properties: {
71
- columns: {
72
- id: { type: :integer, primary_key: true, null: false, array: false },
73
- name: { type: :string, primary_key: false, null: true, array: false },
74
- metadata: { type: :json, primary_key: false, null: true, array: false }
75
- }
76
- }
77
- }
78
-
79
- req_stub = stub_request(:get, /^http:\/\/example.com/).with do |req|
80
- case req.uri.path
81
- when '/tables'
82
- true
83
- when /^\/\w+\/schema$/i
84
- true
85
- else
86
- false
87
- end
88
- end
89
-
90
- req_stub.to_return do |req|
91
- case req.uri.path
92
- when '/tables'
93
- {
94
- body: sunstone_schema.keys.to_json,
95
- headers: { 'StandardAPI-Version' => '5.0.0.5' }
96
- }
97
- when /^\/(\w+)\/schema$/i
98
- {
99
- body: sunstone_schema[$1.to_sym].to_json,
100
- headers: { 'StandardAPI-Version' => '5.0.0.5' }
101
- }
102
- end
103
- end
104
- end
105
-
106
- def debug
107
- ActiveRecord::Base.logger = Logger.new(STDOUT)
108
- $debugging = true
109
- yield
110
- ensure
111
- ActiveRecord::Base.logger = nil
112
- $debugging = false
113
- end
114
-
115
-
116
- class SQLLogger
117
- class << self
118
- attr_accessor :ignored_sql, :log, :log_all
119
- def clear_log; self.log = []; self.log_all = []; end
120
- end
121
-
122
- self.clear_log
123
-
124
- self.ignored_sql = [/^PRAGMA/i, /^SELECT currval/i, /^SELECT CAST/i, /^SELECT @@IDENTITY/i, /^SELECT @@ROWCOUNT/i, /^SAVEPOINT/i, /^ROLLBACK TO SAVEPOINT/i, /^RELEASE SAVEPOINT/i, /^SHOW max_identifier_length/i, /^BEGIN/i, /^COMMIT/i]
125
-
126
- # FIXME: this needs to be refactored so specific database can add their own
127
- # ignored SQL, or better yet, use a different notification for the queries
128
- # instead examining the SQL content.
129
- oracle_ignored = [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im, /^\s*select .* from all_constraints/im, /^\s*select .* from all_tab_cols/im]
130
- mysql_ignored = [/^SHOW FULL TABLES/i, /^SHOW FULL FIELDS/, /^SHOW CREATE TABLE /i, /^SHOW VARIABLES /, /^\s*SELECT (?:column_name|table_name)\b.*\bFROM information_schema\.(?:key_column_usage|tables)\b/im]
131
- postgresql_ignored = [/^\s*select\b.*\bfrom\b.*pg_namespace\b/im, /^\s*select tablename\b.*from pg_tables\b/im, /^\s*select\b.*\battname\b.*\bfrom\b.*\bpg_attribute\b/im, /^SHOW search_path/i]
132
- sqlite3_ignored = [/^\s*SELECT name\b.*\bFROM sqlite_master/im, /^\s*SELECT sql\b.*\bFROM sqlite_master/im]
133
-
134
- [oracle_ignored, mysql_ignored, postgresql_ignored, sqlite3_ignored].each do |db_ignored_sql|
135
- ignored_sql.concat db_ignored_sql
136
- end
137
-
138
- attr_reader :ignore
139
-
140
- def initialize(ignore = Regexp.union(self.class.ignored_sql))
141
- @ignore = ignore
142
- end
143
-
144
- def call(name, start, finish, message_id, values)
145
- sql = values[:sql]
146
-
147
- # FIXME: this seems bad. we should probably have a better way to indicate
148
- # the query was cached
149
- return if 'CACHE' == values[:name]
150
-
151
- self.class.log_all << sql
152
- unless ignore =~ sql
153
- if $debugging
154
- puts caller.select { |l| l.starts_with?(File.expand_path('../../lib', __FILE__)) }
155
- puts "\n\n"
156
- end
157
- end
158
- self.class.log << sql unless ignore =~ sql
159
- end
160
- end
161
- ActiveSupport::Notifications.subscribe('sql.active_record', SQLLogger.new)
162
-
163
- def deep_transform_query(object)
164
- case object
165
- when Hash
166
- object.each_with_object({}) do |(key, value), result|
167
- result[key.to_s] = deep_transform_query(value)
168
- end
169
- when Array
170
- object.map {|e| deep_transform_query(e) }
171
- when Symbol
172
- object.to_s
173
- else
174
- object
175
- end
176
- end
177
-
178
- def assert_sar(query, method, path, query_params = {}, body = nil)
179
- sar = query.to_sar
180
-
181
- assert_equal method, sar.method
182
- assert_equal path, sar.path.split('?').first
183
- assert_equal deep_transform_query(query_params), MessagePack.unpack(CGI::unescape(sar.path.split('?').last))
184
- if body.nil?
185
- assert_nil sar.body
186
- else
187
- assert_equal body, sar.body
188
- end
189
- end
190
-
191
- def assert_sql(expected, query)
192
- assert_equal expected.strip, query.to_sql.strip.gsub(/\s+/, ' ')
193
- end
194
- # test/unit backwards compatibility methods
195
- alias :assert_raise :assert_raises
196
- alias :assert_not_empty :refute_empty
197
- alias :assert_not_equal :refute_equal
198
- alias :assert_not_in_delta :refute_in_delta
199
- alias :assert_not_in_epsilon :refute_in_epsilon
200
- alias :assert_not_includes :refute_includes
201
- alias :assert_not_instance_of :refute_instance_of
202
- alias :assert_not_kind_of :refute_kind_of
203
- alias :assert_no_match :refute_match
204
- alias :assert_not_nil :refute_nil
205
- alias :assert_not_operator :refute_operator
206
- alias :assert_not_predicate :refute_predicate
207
- alias :assert_not_respond_to :refute_respond_to
208
- alias :assert_not_same :refute_same
209
-
210
- end
data/test/ts_test.rb DELETED
@@ -1,151 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TSTest < ActiveSupport::TestCase
4
-
5
- test 'tsquery(query)' do
6
- query = Property.where( Arel::Nodes::TSQuery.new('query') )
7
-
8
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
9
- SELECT "properties".* FROM "properties"
10
- WHERE to_tsquery('query')
11
- SQL
12
- end
13
-
14
- test 'tsquery(query, language: lang)' do
15
- query = Property.where( Arel::Nodes::TSQuery.new('query', language: 'lang') )
16
-
17
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
18
- SELECT "properties".* FROM "properties"
19
- WHERE to_tsquery('lang', 'query')
20
- SQL
21
- end
22
-
23
- test 'tsvector(attribute)' do
24
- query = Property.where( Arel::Nodes::TSVector.new(Property.arel_table[:name]) )
25
-
26
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
27
- SELECT "properties".* FROM "properties"
28
- WHERE to_tsvector("properties"."name")
29
- SQL
30
- end
31
-
32
- test 'tsvector(text)' do
33
- query = Property.where( Arel::Nodes::TSVector.new(
34
- Arel::Nodes::Quoted.new("my data O'Malley")
35
- ))
36
-
37
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
38
- SELECT "properties".* FROM "properties"
39
- WHERE to_tsvector('my data O''Malley')
40
- SQL
41
- end
42
-
43
- test 'tsvector(attribute, language: lang)' do
44
- query = Property.where( Arel::Nodes::TSVector.new(Property.arel_table[:name], language: 'lang') )
45
-
46
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
47
- SELECT "properties".* FROM "properties"
48
- WHERE to_tsvector('lang', "properties"."name")
49
- SQL
50
- end
51
-
52
- test 'ts_match(attrbute, tsquery)' do
53
- query = Property.where(
54
- Arel::Nodes::TSMatch.new(
55
- Property.arel_table[:name],
56
- Arel::Nodes::TSQuery.new('query')
57
- )
58
- )
59
-
60
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
61
- SELECT "properties".* FROM "properties"
62
- WHERE "properties"."name" @@ to_tsquery('query')
63
- SQL
64
- end
65
-
66
- test 'ts_match(tsvector, tsquery)' do
67
- query = Property.where(
68
- Arel::Nodes::TSMatch.new(
69
- Arel::Nodes::TSVector.new(Property.arel_table[:name]),
70
- Arel::Nodes::TSQuery.new('query')
71
- )
72
- )
73
-
74
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
75
- SELECT "properties".* FROM "properties"
76
- WHERE to_tsvector("properties"."name") @@ to_tsquery('query')
77
- SQL
78
- end
79
-
80
- test 'ts_rank(attribute, tsquery)' do
81
- query = Property.where(
82
- Arel::Nodes::TSRank.new(
83
- Property.arel_table[:name],
84
- Arel::Nodes::TSQuery.new('query')
85
- )
86
- )
87
-
88
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
89
- SELECT "properties".* FROM "properties"
90
- WHERE ts_rank("properties"."name", to_tsquery('query'))
91
- SQL
92
- end
93
-
94
- test 'ts_rank(tsvector, tsquery)' do
95
- query = Property.where(
96
- Arel::Nodes::TSRank.new(
97
- Arel::Nodes::TSVector.new(Property.arel_table[:name]),
98
- Arel::Nodes::TSQuery.new('query')
99
- )
100
- )
101
-
102
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
103
- SELECT "properties".* FROM "properties"
104
- WHERE ts_rank(to_tsvector("properties"."name"), to_tsquery('query'))
105
- SQL
106
- end
107
-
108
- test 'ts_rank_cd(attribute, tsquery)' do
109
- query = Property.where(
110
- Arel::Nodes::TSRankCD.new(
111
- Property.arel_table[:name],
112
- Arel::Nodes::TSQuery.new('query')
113
- )
114
- )
115
-
116
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
117
- SELECT "properties".* FROM "properties"
118
- WHERE ts_rank_cd("properties"."name", to_tsquery('query'))
119
- SQL
120
- end
121
-
122
- test 'ts_rank_cd(tsvector, tsquery)' do
123
- query = Property.where(
124
- Arel::Nodes::TSRankCD.new(
125
- Arel::Nodes::TSVector.new(Property.arel_table[:name]),
126
- Arel::Nodes::TSQuery.new('query')
127
- )
128
- )
129
-
130
- assert_equal(<<~SQL.gsub(/( +|\n)/, ' ').strip, query.to_sql)
131
- SELECT "properties".* FROM "properties"
132
- WHERE ts_rank_cd(to_tsvector("properties"."name"), to_tsquery('query'))
133
- SQL
134
- end
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
-
151
- end