ransack 3.1.0 → 4.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.
- checksums.yaml +4 -4
- data/.github/workflows/codeql.yml +72 -0
- data/.github/workflows/test.yml +22 -27
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +79 -0
- data/CONTRIBUTING.md +38 -16
- data/Gemfile +10 -10
- data/README.md +8 -13
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +4 -0
- data/docs/docs/getting-started/advanced-mode.md +1 -1
- data/docs/docs/getting-started/search-matches.md +1 -1
- data/docs/docs/getting-started/simple-mode.md +30 -26
- data/docs/docs/getting-started/sorting.md +1 -1
- data/docs/docs/going-further/acts-as-taggable-on.md +10 -10
- data/docs/docs/going-further/exporting-to-csv.md +2 -2
- data/docs/docs/going-further/form-customisation.md +1 -1
- data/docs/docs/going-further/i18n.md +3 -3
- data/docs/docs/going-further/other-notes.md +1 -1
- data/docs/docs/going-further/saving-queries.md +1 -1
- data/docs/docs/going-further/searching-postgres.md +1 -1
- data/docs/docs/intro.md +2 -2
- data/docs/docusaurus.config.js +14 -1
- data/docs/package.json +7 -2
- data/docs/yarn.lock +3036 -1917
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -1
- data/lib/ransack/adapters/active_record/base.rb +78 -7
- data/lib/ransack/adapters/active_record/context.rb +17 -49
- data/lib/ransack/configuration.rb +25 -12
- data/lib/ransack/constants.rb +125 -3
- data/lib/ransack/context.rb +34 -5
- data/lib/ransack/helpers/form_builder.rb +3 -3
- data/lib/ransack/helpers/form_helper.rb +4 -3
- data/lib/ransack/nodes/attribute.rb +2 -2
- data/lib/ransack/nodes/condition.rb +80 -7
- data/lib/ransack/nodes/grouping.rb +3 -3
- data/lib/ransack/nodes/node.rb +1 -1
- data/lib/ransack/nodes/value.rb +2 -2
- data/lib/ransack/predicate.rb +1 -1
- data/lib/ransack/ransacker.rb +1 -1
- data/lib/ransack/search.rb +9 -4
- data/lib/ransack/translate.rb +2 -2
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +38 -2
- data/lib/ransack.rb +3 -6
- data/ransack.gemspec +2 -2
- data/spec/helpers/polyamorous_helper.rb +2 -8
- data/spec/ransack/adapters/active_record/base_spec.rb +73 -0
- data/spec/ransack/configuration_spec.rb +9 -9
- data/spec/ransack/helpers/form_builder_spec.rb +8 -8
- data/spec/ransack/helpers/form_helper_spec.rb +48 -2
- data/spec/ransack/nodes/condition_spec.rb +24 -0
- data/spec/ransack/nodes/value_spec.rb +115 -0
- data/spec/ransack/predicate_spec.rb +36 -1
- data/spec/ransack/translate_spec.rb +1 -1
- data/spec/support/schema.rb +27 -10
- metadata +11 -19
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +0 -20
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +0 -79
- data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +0 -11
- data/lib/polyamorous.rb +0 -1
- data/lib/ransack/adapters/active_record/ransack/constants.rb +0 -128
- data/lib/ransack/adapters/active_record/ransack/context.rb +0 -56
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +0 -69
- data/lib/ransack/adapters/active_record/ransack/translate.rb +0 -8
- data/lib/ransack/adapters/active_record/ransack/visitor.rb +0 -47
- data/lib/ransack/adapters.rb +0 -64
- data/lib/ransack/nodes.rb +0 -8
- /data/lib/ransack/{adapters/active_record.rb → active_record.rb} +0 -0
@@ -35,6 +35,13 @@ module Ransack
|
|
35
35
|
@s.awesome_eq = nil
|
36
36
|
expect(@s.result.to_sql).not_to match /WHERE/
|
37
37
|
end
|
38
|
+
|
39
|
+
it 'generates a = condition with a huge integer value' do
|
40
|
+
val = 123456789012345678901
|
41
|
+
@s.salary_eq = val
|
42
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
43
|
+
expect(@s.result.to_sql).to match /#{field} = #{val}/
|
44
|
+
end
|
38
45
|
end
|
39
46
|
|
40
47
|
describe 'lteq' do
|
@@ -56,6 +63,13 @@ module Ransack
|
|
56
63
|
@s.salary_lteq = nil
|
57
64
|
expect(@s.result.to_sql).not_to match /WHERE/
|
58
65
|
end
|
66
|
+
|
67
|
+
it 'generates a <= condition with a huge integer value' do
|
68
|
+
val = 123456789012345678901
|
69
|
+
@s.salary_lteq = val
|
70
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
71
|
+
expect(@s.result.to_sql).to match /#{field} <= #{val}/
|
72
|
+
end
|
59
73
|
end
|
60
74
|
|
61
75
|
describe 'lt' do
|
@@ -77,6 +91,13 @@ module Ransack
|
|
77
91
|
@s.salary_lt = nil
|
78
92
|
expect(@s.result.to_sql).not_to match /WHERE/
|
79
93
|
end
|
94
|
+
|
95
|
+
it 'generates a = condition with a huge integer value' do
|
96
|
+
val = 123456789012345678901
|
97
|
+
@s.salary_lt = val
|
98
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
99
|
+
expect(@s.result.to_sql).to match /#{field} < #{val}/
|
100
|
+
end
|
80
101
|
end
|
81
102
|
|
82
103
|
describe 'gteq' do
|
@@ -98,6 +119,13 @@ module Ransack
|
|
98
119
|
@s.salary_gteq = nil
|
99
120
|
expect(@s.result.to_sql).not_to match /WHERE/
|
100
121
|
end
|
122
|
+
|
123
|
+
it 'generates a >= condition with a huge integer value' do
|
124
|
+
val = 123456789012345678901
|
125
|
+
@s.salary_gteq = val
|
126
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
127
|
+
expect(@s.result.to_sql).to match /#{field} >= #{val}/
|
128
|
+
end
|
101
129
|
end
|
102
130
|
|
103
131
|
describe 'gt' do
|
@@ -119,6 +147,13 @@ module Ransack
|
|
119
147
|
@s.salary_gt = nil
|
120
148
|
expect(@s.result.to_sql).not_to match /WHERE/
|
121
149
|
end
|
150
|
+
|
151
|
+
it 'generates a > condition with a huge integer value' do
|
152
|
+
val = 123456789012345678901
|
153
|
+
@s.salary_gt = val
|
154
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
155
|
+
expect(@s.result.to_sql).to match /#{field} > #{val}/
|
156
|
+
end
|
122
157
|
end
|
123
158
|
|
124
159
|
describe 'cont' do
|
@@ -368,7 +403,7 @@ module Ransack
|
|
368
403
|
expect(@s.result.to_sql).to match /#{field} IS NULL/
|
369
404
|
end
|
370
405
|
|
371
|
-
describe 'with association
|
406
|
+
describe 'with association query' do
|
372
407
|
it 'generates a value IS NOT NULL query' do
|
373
408
|
@s.comments_id_not_null = true
|
374
409
|
sql = @s.result.to_sql
|
@@ -8,7 +8,7 @@ module Ransack
|
|
8
8
|
ar_translation = ::Namespace::Article.human_attribute_name(:title)
|
9
9
|
ransack_translation = Ransack::Translate.attribute(
|
10
10
|
:title,
|
11
|
-
:
|
11
|
+
context: ::Namespace::Article.ransack.context
|
12
12
|
)
|
13
13
|
expect(ransack_translation).to eq ar_translation
|
14
14
|
end
|
data/spec/support/schema.rb
CHANGED
@@ -28,7 +28,24 @@ else
|
|
28
28
|
)
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
# This is just a test app with no sensitive data, so we explicitly allowlist all
|
32
|
+
# attributes and associations for search. In general, end users should
|
33
|
+
# explicitly authorize each model, but this shows a way to configure the
|
34
|
+
# unrestricted default behavior of versions prior to Ransack 4.
|
35
|
+
#
|
36
|
+
class ApplicationRecord < ActiveRecord::Base
|
37
|
+
self.abstract_class = true
|
38
|
+
|
39
|
+
def self.ransackable_attributes(auth_object = nil)
|
40
|
+
authorizable_ransackable_attributes
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.ransackable_associations(auth_object = nil)
|
44
|
+
authorizable_ransackable_associations
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Person < ApplicationRecord
|
32
49
|
default_scope { order(id: :desc) }
|
33
50
|
belongs_to :parent, class_name: 'Person', foreign_key: :parent_id
|
34
51
|
has_many :children, class_name: 'Person', foreign_key: :parent_id
|
@@ -111,9 +128,9 @@ class Person < ActiveRecord::Base
|
|
111
128
|
|
112
129
|
def self.ransackable_attributes(auth_object = nil)
|
113
130
|
if auth_object == :admin
|
114
|
-
|
131
|
+
authorizable_ransackable_attributes - ['only_sort']
|
115
132
|
else
|
116
|
-
|
133
|
+
authorizable_ransackable_attributes - ['only_sort', 'only_admin']
|
117
134
|
end
|
118
135
|
end
|
119
136
|
|
@@ -129,7 +146,7 @@ end
|
|
129
146
|
class Musician < Person
|
130
147
|
end
|
131
148
|
|
132
|
-
class Article <
|
149
|
+
class Article < ApplicationRecord
|
133
150
|
belongs_to :person
|
134
151
|
has_many :comments
|
135
152
|
has_and_belongs_to_many :tags
|
@@ -182,7 +199,7 @@ end
|
|
182
199
|
class StoryArticle < Article
|
183
200
|
end
|
184
201
|
|
185
|
-
class Recommendation <
|
202
|
+
class Recommendation < ApplicationRecord
|
186
203
|
belongs_to :person
|
187
204
|
belongs_to :target_person, class_name: 'Person'
|
188
205
|
belongs_to :article
|
@@ -200,22 +217,22 @@ module Namespace
|
|
200
217
|
end
|
201
218
|
end
|
202
219
|
|
203
|
-
class Comment <
|
220
|
+
class Comment < ApplicationRecord
|
204
221
|
belongs_to :article
|
205
222
|
belongs_to :person
|
206
223
|
|
207
224
|
default_scope { where(disabled: false) }
|
208
225
|
end
|
209
226
|
|
210
|
-
class Tag <
|
227
|
+
class Tag < ApplicationRecord
|
211
228
|
has_and_belongs_to_many :articles
|
212
229
|
end
|
213
230
|
|
214
|
-
class Note <
|
231
|
+
class Note < ApplicationRecord
|
215
232
|
belongs_to :notable, polymorphic: true
|
216
233
|
end
|
217
234
|
|
218
|
-
class Account <
|
235
|
+
class Account < ApplicationRecord
|
219
236
|
belongs_to :agent_account, class_name: "Account"
|
220
237
|
belongs_to :trade_account, class_name: "Account"
|
221
238
|
end
|
@@ -308,7 +325,7 @@ module Schema
|
|
308
325
|
end
|
309
326
|
|
310
327
|
module SubDB
|
311
|
-
class Base <
|
328
|
+
class Base < ApplicationRecord
|
312
329
|
self.abstract_class = true
|
313
330
|
establish_connection(
|
314
331
|
adapter: 'sqlite3',
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ransack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernie Miller
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2023-02-09 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activerecord
|
@@ -20,28 +20,28 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 6.
|
23
|
+
version: 6.1.5
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
28
|
- - ">="
|
29
29
|
- !ruby/object:Gem::Version
|
30
|
-
version: 6.
|
30
|
+
version: 6.1.5
|
31
31
|
- !ruby/object:Gem::Dependency
|
32
32
|
name: activesupport
|
33
33
|
requirement: !ruby/object:Gem::Requirement
|
34
34
|
requirements:
|
35
35
|
- - ">="
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 6.
|
37
|
+
version: 6.1.5
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
requirements:
|
42
42
|
- - ">="
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
version: 6.
|
44
|
+
version: 6.1.5
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
46
|
name: i18n
|
47
47
|
requirement: !ruby/object:Gem::Requirement
|
@@ -69,6 +69,7 @@ extra_rdoc_files: []
|
|
69
69
|
files:
|
70
70
|
- ".github/FUNDING.yml"
|
71
71
|
- ".github/SECURITY.md"
|
72
|
+
- ".github/workflows/codeql.yml"
|
72
73
|
- ".github/workflows/cronjob.yml"
|
73
74
|
- ".github/workflows/deploy.yml"
|
74
75
|
- ".github/workflows/rubocop.yml"
|
@@ -139,10 +140,6 @@ files:
|
|
139
140
|
- docs/static/logo/ransack.png
|
140
141
|
- docs/static/logo/ransack.svg
|
141
142
|
- docs/yarn.lock
|
142
|
-
- lib/polyamorous.rb
|
143
|
-
- lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb
|
144
|
-
- lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb
|
145
|
-
- lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb
|
146
143
|
- lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb
|
147
144
|
- lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb
|
148
145
|
- lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb
|
@@ -157,15 +154,9 @@ files:
|
|
157
154
|
- lib/polyamorous/swapping_reflection_class.rb
|
158
155
|
- lib/polyamorous/tree_node.rb
|
159
156
|
- lib/ransack.rb
|
160
|
-
- lib/ransack/
|
161
|
-
- lib/ransack/adapters/active_record.rb
|
157
|
+
- lib/ransack/active_record.rb
|
162
158
|
- lib/ransack/adapters/active_record/base.rb
|
163
159
|
- lib/ransack/adapters/active_record/context.rb
|
164
|
-
- lib/ransack/adapters/active_record/ransack/constants.rb
|
165
|
-
- lib/ransack/adapters/active_record/ransack/context.rb
|
166
|
-
- lib/ransack/adapters/active_record/ransack/nodes/condition.rb
|
167
|
-
- lib/ransack/adapters/active_record/ransack/translate.rb
|
168
|
-
- lib/ransack/adapters/active_record/ransack/visitor.rb
|
169
160
|
- lib/ransack/configuration.rb
|
170
161
|
- lib/ransack/constants.rb
|
171
162
|
- lib/ransack/context.rb
|
@@ -199,7 +190,6 @@ files:
|
|
199
190
|
- lib/ransack/locale/zh-CN.yml
|
200
191
|
- lib/ransack/locale/zh-TW.yml
|
201
192
|
- lib/ransack/naming.rb
|
202
|
-
- lib/ransack/nodes.rb
|
203
193
|
- lib/ransack/nodes/attribute.rb
|
204
194
|
- lib/ransack/nodes/bindable.rb
|
205
195
|
- lib/ransack/nodes/condition.rb
|
@@ -233,6 +223,7 @@ files:
|
|
233
223
|
- spec/ransack/helpers/form_helper_spec.rb
|
234
224
|
- spec/ransack/nodes/condition_spec.rb
|
235
225
|
- spec/ransack/nodes/grouping_spec.rb
|
226
|
+
- spec/ransack/nodes/value_spec.rb
|
236
227
|
- spec/ransack/predicate_spec.rb
|
237
228
|
- spec/ransack/search_spec.rb
|
238
229
|
- spec/ransack/translate_spec.rb
|
@@ -258,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
258
249
|
- !ruby/object:Gem::Version
|
259
250
|
version: '0'
|
260
251
|
requirements: []
|
261
|
-
rubygems_version: 3.
|
252
|
+
rubygems_version: 3.4.6
|
262
253
|
signing_key:
|
263
254
|
specification_version: 4
|
264
255
|
summary: Object-based searching for Active Record.
|
@@ -282,6 +273,7 @@ test_files:
|
|
282
273
|
- spec/ransack/helpers/form_helper_spec.rb
|
283
274
|
- spec/ransack/nodes/condition_spec.rb
|
284
275
|
- spec/ransack/nodes/grouping_spec.rb
|
276
|
+
- spec/ransack/nodes/value_spec.rb
|
285
277
|
- spec/ransack/predicate_spec.rb
|
286
278
|
- spec/ransack/search_spec.rb
|
287
279
|
- spec/ransack/translate_spec.rb
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Polyamorous
|
2
|
-
module JoinAssociationExtensions
|
3
|
-
include SwappingReflectionClass
|
4
|
-
def self.prepended(base)
|
5
|
-
base.class_eval { attr_reader :join_type }
|
6
|
-
end
|
7
|
-
|
8
|
-
def initialize(reflection, children, polymorphic_class = nil, join_type = Arel::Nodes::InnerJoin)
|
9
|
-
@join_type = join_type
|
10
|
-
if polymorphic_class && ::ActiveRecord::Base > polymorphic_class
|
11
|
-
swapping_reflection_klass(reflection, polymorphic_class) do |reflection|
|
12
|
-
super(reflection, children)
|
13
|
-
self.reflection.options[:polymorphic] = true
|
14
|
-
end
|
15
|
-
else
|
16
|
-
super(reflection, children)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,79 +0,0 @@
|
|
1
|
-
module Polyamorous
|
2
|
-
module JoinDependencyExtensions
|
3
|
-
# Replaces ActiveRecord::Associations::JoinDependency#build
|
4
|
-
def build(associations, base_klass)
|
5
|
-
associations.map do |name, right|
|
6
|
-
if name.is_a? Join
|
7
|
-
reflection = find_reflection base_klass, name.name
|
8
|
-
reflection.check_validity!
|
9
|
-
reflection.check_eager_loadable!
|
10
|
-
|
11
|
-
klass = if reflection.polymorphic?
|
12
|
-
name.klass || base_klass
|
13
|
-
else
|
14
|
-
reflection.klass
|
15
|
-
end
|
16
|
-
JoinAssociation.new(reflection, build(right, klass), name.klass, name.type)
|
17
|
-
else
|
18
|
-
reflection = find_reflection base_klass, name
|
19
|
-
reflection.check_validity!
|
20
|
-
reflection.check_eager_loadable!
|
21
|
-
|
22
|
-
if reflection.polymorphic?
|
23
|
-
raise ActiveRecord::EagerLoadPolymorphicError.new(reflection)
|
24
|
-
end
|
25
|
-
JoinAssociation.new(reflection, build(right, reflection.klass))
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def join_constraints(joins_to_add, alias_tracker)
|
31
|
-
@alias_tracker = alias_tracker
|
32
|
-
|
33
|
-
construct_tables!(join_root)
|
34
|
-
joins = make_join_constraints(join_root, join_type)
|
35
|
-
|
36
|
-
joins.concat joins_to_add.flat_map { |oj|
|
37
|
-
construct_tables!(oj.join_root)
|
38
|
-
if join_root.match?(oj.join_root) && join_root.table.name == oj.join_root.table.name
|
39
|
-
walk join_root, oj.join_root, oj.join_type
|
40
|
-
else
|
41
|
-
make_join_constraints(oj.join_root, oj.join_type)
|
42
|
-
end
|
43
|
-
}
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
def make_constraints(parent, child, join_type = Arel::Nodes::OuterJoin)
|
48
|
-
foreign_table = parent.table
|
49
|
-
foreign_klass = parent.base_klass
|
50
|
-
join_type = child.join_type || join_type if join_type == Arel::Nodes::InnerJoin
|
51
|
-
joins = child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
|
52
|
-
joins.concat child.children.flat_map { |c| make_constraints(child, c, join_type) }
|
53
|
-
end
|
54
|
-
|
55
|
-
module ClassMethods
|
56
|
-
# Prepended before ActiveRecord::Associations::JoinDependency#walk_tree
|
57
|
-
#
|
58
|
-
def walk_tree(associations, hash)
|
59
|
-
case associations
|
60
|
-
when TreeNode
|
61
|
-
associations.add_to_tree(hash)
|
62
|
-
when Hash
|
63
|
-
associations.each do |k, v|
|
64
|
-
cache =
|
65
|
-
if TreeNode === k
|
66
|
-
k.add_to_tree(hash)
|
67
|
-
else
|
68
|
-
hash[k] ||= {}
|
69
|
-
end
|
70
|
-
walk_tree(v, cache)
|
71
|
-
end
|
72
|
-
else
|
73
|
-
super(associations, hash)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
end
|
data/lib/polyamorous.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'polyamorous/polyamorous'
|
@@ -1,128 +0,0 @@
|
|
1
|
-
module Ransack
|
2
|
-
module Constants
|
3
|
-
DISTINCT = 'DISTINCT '.freeze
|
4
|
-
|
5
|
-
DERIVED_PREDICATES = [
|
6
|
-
[CONT, {
|
7
|
-
arel_predicate: 'matches'.freeze,
|
8
|
-
formatter: proc { |v| "%#{escape_wildcards(v)}%" }
|
9
|
-
}
|
10
|
-
],
|
11
|
-
['not_cont'.freeze, {
|
12
|
-
arel_predicate: 'does_not_match'.freeze,
|
13
|
-
formatter: proc { |v| "%#{escape_wildcards(v)}%" }
|
14
|
-
}
|
15
|
-
],
|
16
|
-
['i_cont'.freeze, {
|
17
|
-
arel_predicate: 'matches'.freeze,
|
18
|
-
formatter: proc { |v| "%#{escape_wildcards(v.downcase)}%" },
|
19
|
-
case_insensitive: true
|
20
|
-
}
|
21
|
-
],
|
22
|
-
['not_i_cont'.freeze, {
|
23
|
-
arel_predicate: 'does_not_match'.freeze,
|
24
|
-
formatter: proc { |v| "%#{escape_wildcards(v.downcase)}%" },
|
25
|
-
case_insensitive: true
|
26
|
-
}
|
27
|
-
],
|
28
|
-
['start'.freeze, {
|
29
|
-
arel_predicate: 'matches'.freeze,
|
30
|
-
formatter: proc { |v| "#{escape_wildcards(v)}%" }
|
31
|
-
}
|
32
|
-
],
|
33
|
-
['not_start'.freeze, {
|
34
|
-
arel_predicate: 'does_not_match'.freeze,
|
35
|
-
formatter: proc { |v| "#{escape_wildcards(v)}%" }
|
36
|
-
}
|
37
|
-
],
|
38
|
-
['end'.freeze, {
|
39
|
-
arel_predicate: 'matches'.freeze,
|
40
|
-
formatter: proc { |v| "%#{escape_wildcards(v)}" }
|
41
|
-
}
|
42
|
-
],
|
43
|
-
['not_end'.freeze, {
|
44
|
-
arel_predicate: 'does_not_match'.freeze,
|
45
|
-
formatter: proc { |v| "%#{escape_wildcards(v)}" }
|
46
|
-
}
|
47
|
-
],
|
48
|
-
['true'.freeze, {
|
49
|
-
arel_predicate: proc { |v| v ? EQ : NOT_EQ },
|
50
|
-
compounds: false,
|
51
|
-
type: :boolean,
|
52
|
-
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
53
|
-
formatter: proc { |v| true }
|
54
|
-
}
|
55
|
-
],
|
56
|
-
['not_true'.freeze, {
|
57
|
-
arel_predicate: proc { |v| v ? NOT_EQ : EQ },
|
58
|
-
compounds: false,
|
59
|
-
type: :boolean,
|
60
|
-
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
61
|
-
formatter: proc { |v| true }
|
62
|
-
}
|
63
|
-
],
|
64
|
-
['false'.freeze, {
|
65
|
-
arel_predicate: proc { |v| v ? EQ : NOT_EQ },
|
66
|
-
compounds: false,
|
67
|
-
type: :boolean,
|
68
|
-
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
69
|
-
formatter: proc { |v| false }
|
70
|
-
}
|
71
|
-
],
|
72
|
-
['not_false'.freeze, {
|
73
|
-
arel_predicate: proc { |v| v ? NOT_EQ : EQ },
|
74
|
-
compounds: false,
|
75
|
-
type: :boolean,
|
76
|
-
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
77
|
-
formatter: proc { |v| false }
|
78
|
-
}
|
79
|
-
],
|
80
|
-
['present'.freeze, {
|
81
|
-
arel_predicate: proc { |v| v ? NOT_EQ_ALL : EQ_ANY },
|
82
|
-
compounds: false,
|
83
|
-
type: :boolean,
|
84
|
-
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
85
|
-
formatter: proc { |v| [nil, ''.freeze].freeze }
|
86
|
-
}
|
87
|
-
],
|
88
|
-
['blank'.freeze, {
|
89
|
-
arel_predicate: proc { |v| v ? EQ_ANY : NOT_EQ_ALL },
|
90
|
-
compounds: false,
|
91
|
-
type: :boolean,
|
92
|
-
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
93
|
-
formatter: proc { |v| [nil, ''.freeze].freeze }
|
94
|
-
}
|
95
|
-
],
|
96
|
-
['null'.freeze, {
|
97
|
-
arel_predicate: proc { |v| v ? EQ : NOT_EQ },
|
98
|
-
compounds: false,
|
99
|
-
type: :boolean,
|
100
|
-
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
101
|
-
formatter: proc { |v| nil }
|
102
|
-
}
|
103
|
-
],
|
104
|
-
['not_null'.freeze, {
|
105
|
-
arel_predicate: proc { |v| v ? NOT_EQ : EQ },
|
106
|
-
compounds: false,
|
107
|
-
type: :boolean,
|
108
|
-
validator: proc { |v| BOOLEAN_VALUES.include?(v) },
|
109
|
-
formatter: proc { |v| nil } }
|
110
|
-
]
|
111
|
-
].freeze
|
112
|
-
|
113
|
-
module_function
|
114
|
-
# replace % \ to \% \\
|
115
|
-
def escape_wildcards(unescaped)
|
116
|
-
case ActiveRecord::Base.connection.adapter_name
|
117
|
-
when "Mysql2".freeze
|
118
|
-
# Necessary for MySQL
|
119
|
-
unescaped.to_s.gsub(/([\\%_])/, '\\\\\\1')
|
120
|
-
when "PostgreSQL".freeze
|
121
|
-
# Necessary for PostgreSQL
|
122
|
-
unescaped.to_s.gsub(/([\\%_.])/, '\\\\\\1')
|
123
|
-
else
|
124
|
-
unescaped
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'ransack/visitor'
|
2
|
-
|
3
|
-
module Ransack
|
4
|
-
class Context
|
5
|
-
attr_reader :arel_visitor
|
6
|
-
|
7
|
-
class << self
|
8
|
-
|
9
|
-
def for_class(klass, options = {})
|
10
|
-
if klass < ActiveRecord::Base
|
11
|
-
Adapters::ActiveRecord::Context.new(klass, options)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def for_object(object, options = {})
|
16
|
-
case object
|
17
|
-
when ActiveRecord::Relation
|
18
|
-
Adapters::ActiveRecord::Context.new(object.klass, options)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
end # << self
|
23
|
-
|
24
|
-
def initialize(object, options = {})
|
25
|
-
@object = relation_for(object)
|
26
|
-
@klass = @object.klass
|
27
|
-
@join_dependency = join_dependency(@object)
|
28
|
-
@join_type = options[:join_type] || Polyamorous::OuterJoin
|
29
|
-
@search_key = options[:search_key] || Ransack.options[:search_key]
|
30
|
-
@associations_pot = {}
|
31
|
-
@tables_pot = {}
|
32
|
-
@lock_associations = []
|
33
|
-
|
34
|
-
@base = @join_dependency.instance_variable_get(:@join_root)
|
35
|
-
end
|
36
|
-
|
37
|
-
def bind_pair_for(key)
|
38
|
-
@bind_pairs ||= {}
|
39
|
-
|
40
|
-
@bind_pairs[key] ||= begin
|
41
|
-
parent, attr_name = get_parent_and_attribute_name(key.to_s)
|
42
|
-
[parent, attr_name] if parent && attr_name
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def klassify(obj)
|
47
|
-
if Class === obj && ::ActiveRecord::Base > obj
|
48
|
-
obj
|
49
|
-
elsif obj.respond_to? :klass
|
50
|
-
obj.klass
|
51
|
-
else
|
52
|
-
raise ArgumentError, "Don't know how to klassify #{obj.inspect}"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
module Ransack
|
2
|
-
module Nodes
|
3
|
-
class Condition
|
4
|
-
|
5
|
-
def arel_predicate
|
6
|
-
attributes.map { |attribute|
|
7
|
-
association = attribute.parent
|
8
|
-
if negative? && attribute.associated_collection?
|
9
|
-
query = context.build_correlated_subquery(association)
|
10
|
-
context.remove_association(association)
|
11
|
-
if self.predicate_name == 'not_null' && self.value
|
12
|
-
query.where(format_predicate(attribute))
|
13
|
-
Arel::Nodes::In.new(context.primary_key, Arel.sql(query.to_sql))
|
14
|
-
else
|
15
|
-
query.where(format_predicate(attribute).not)
|
16
|
-
Arel::Nodes::NotIn.new(context.primary_key, Arel.sql(query.to_sql))
|
17
|
-
end
|
18
|
-
else
|
19
|
-
format_predicate(attribute)
|
20
|
-
end
|
21
|
-
}.reduce(combinator_method)
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def combinator_method
|
27
|
-
combinator === Constants::OR ? :or : :and
|
28
|
-
end
|
29
|
-
|
30
|
-
def format_predicate(attribute)
|
31
|
-
arel_pred = arel_predicate_for_attribute(attribute)
|
32
|
-
arel_values = formatted_values_for_attribute(attribute)
|
33
|
-
predicate = attr_value_for_attribute(attribute).public_send(arel_pred, arel_values)
|
34
|
-
|
35
|
-
if in_predicate?(predicate)
|
36
|
-
predicate.right = predicate.right.map do |pr|
|
37
|
-
casted_array?(pr) ? format_values_for(pr) : pr
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
predicate
|
42
|
-
end
|
43
|
-
|
44
|
-
def in_predicate?(predicate)
|
45
|
-
return unless defined?(Arel::Nodes::Casted)
|
46
|
-
predicate.class == Arel::Nodes::In || predicate.class == Arel::Nodes::NotIn
|
47
|
-
end
|
48
|
-
|
49
|
-
def casted_array?(predicate)
|
50
|
-
value_from(predicate).is_a?(Array) && predicate.is_a?(Arel::Nodes::Casted)
|
51
|
-
end
|
52
|
-
|
53
|
-
def value_from(predicate)
|
54
|
-
if predicate.respond_to?(:value)
|
55
|
-
predicate.value # Rails 6.1
|
56
|
-
elsif predicate.respond_to?(:val)
|
57
|
-
predicate.val # Rails 6.0
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def format_values_for(predicate)
|
62
|
-
value_from(predicate).map do |val|
|
63
|
-
val.is_a?(String) ? Arel::Nodes.build_quoted(val) : val
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|