ransack 2.3.2 → 4.1.1
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/FUNDING.yml +3 -0
- data/.github/SECURITY.md +12 -0
- data/.github/workflows/codeql.yml +72 -0
- data/.github/workflows/cronjob.yml +99 -0
- data/.github/workflows/deploy.yml +35 -0
- data/.github/workflows/rubocop.yml +20 -0
- data/.github/workflows/test-deploy.yml +29 -0
- data/.github/workflows/test.yml +131 -0
- data/.nojekyll +0 -0
- data/.rubocop.yml +50 -0
- data/CHANGELOG.md +251 -1
- data/CONTRIBUTING.md +51 -29
- data/Gemfile +12 -10
- data/README.md +45 -907
- data/bug_report_templates/test-ransack-scope-and-column-same-name.rb +78 -0
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +75 -0
- data/docs/.gitignore +19 -0
- data/docs/.nojekyll +0 -0
- data/docs/babel.config.js +3 -0
- data/docs/blog/2022-03-27-ransack-3.0.0.md +20 -0
- data/docs/docs/getting-started/_category_.json +4 -0
- data/docs/docs/getting-started/advanced-mode.md +46 -0
- data/docs/docs/getting-started/configuration.md +47 -0
- data/docs/docs/getting-started/search-matches.md +67 -0
- data/docs/docs/getting-started/simple-mode.md +288 -0
- data/docs/docs/getting-started/sorting.md +71 -0
- data/docs/docs/getting-started/using-predicates.md +282 -0
- data/docs/docs/going-further/_category_.json +4 -0
- data/docs/docs/going-further/acts-as-taggable-on.md +114 -0
- data/docs/docs/going-further/associations.md +70 -0
- data/docs/docs/going-further/custom-predicates.md +52 -0
- data/docs/docs/going-further/documentation.md +43 -0
- data/docs/docs/going-further/exporting-to-csv.md +49 -0
- data/docs/docs/going-further/external-guides.md +57 -0
- data/docs/docs/going-further/form-customisation.md +63 -0
- data/docs/docs/going-further/i18n.md +53 -0
- data/docs/docs/going-further/img/create_release.png +0 -0
- data/docs/docs/going-further/merging-searches.md +41 -0
- data/docs/docs/going-further/other-notes.md +428 -0
- data/docs/docs/going-further/polymorphic-search.md +46 -0
- data/docs/docs/going-further/ransackers.md +331 -0
- data/docs/docs/going-further/release_process.md +36 -0
- data/docs/docs/going-further/saving-queries.md +82 -0
- data/docs/docs/going-further/searching-postgres.md +57 -0
- data/docs/docs/going-further/wiki-contributors.md +82 -0
- data/docs/docs/intro.md +99 -0
- data/docs/docusaurus.config.js +120 -0
- data/docs/package.json +42 -0
- data/docs/sidebars.js +31 -0
- data/docs/src/components/HomepageFeatures/index.js +64 -0
- data/docs/src/components/HomepageFeatures/styles.module.css +11 -0
- data/docs/src/css/custom.css +39 -0
- data/docs/src/pages/index.module.css +23 -0
- data/docs/src/pages/markdown-page.md +7 -0
- data/docs/static/.nojekyll +0 -0
- data/docs/static/img/docusaurus.png +0 -0
- data/docs/static/img/favicon.ico +0 -0
- data/docs/static/img/logo.svg +1 -0
- data/docs/static/img/tutorial/docsVersionDropdown.png +0 -0
- data/docs/static/img/tutorial/localeDropdown.png +0 -0
- data/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
- data/docs/static/img/undraw_docusaurus_react.svg +170 -0
- data/docs/static/img/undraw_docusaurus_tree.svg +40 -0
- data/docs/yarn.lock +8879 -0
- data/lib/polyamorous/activerecord/join_association.rb +70 -0
- data/{polyamorous/lib/polyamorous/activerecord_6.0_ruby_2 → lib/polyamorous/activerecord}/join_dependency.rb +33 -12
- data/lib/polyamorous/activerecord/reflection.rb +11 -0
- data/{polyamorous/lib → lib/polyamorous}/polyamorous.rb +3 -4
- data/lib/ransack/adapters/active_record/base.rb +83 -10
- data/lib/ransack/adapters/active_record/context.rb +56 -44
- data/lib/ransack/configuration.rb +53 -10
- data/lib/ransack/constants.rb +126 -4
- data/lib/ransack/context.rb +34 -5
- data/lib/ransack/helpers/form_builder.rb +6 -6
- data/lib/ransack/helpers/form_helper.rb +14 -5
- data/lib/ransack/helpers.rb +1 -1
- data/lib/ransack/locale/sv.yml +70 -0
- data/lib/ransack/nodes/attribute.rb +3 -3
- data/lib/ransack/nodes/condition.rb +80 -9
- data/lib/ransack/nodes/grouping.rb +4 -4
- data/lib/ransack/nodes/node.rb +1 -1
- data/lib/ransack/nodes/sort.rb +3 -3
- data/lib/ransack/nodes/value.rb +3 -3
- data/lib/ransack/predicate.rb +1 -1
- data/lib/ransack/ransacker.rb +1 -1
- data/lib/ransack/search.rb +15 -7
- data/lib/ransack/translate.rb +6 -6
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +38 -2
- data/lib/ransack.rb +5 -8
- data/ransack.gemspec +9 -15
- data/spec/blueprints/articles.rb +1 -1
- data/spec/blueprints/comments.rb +1 -1
- data/spec/blueprints/notes.rb +1 -1
- data/spec/blueprints/tags.rb +1 -1
- data/spec/console.rb +5 -5
- data/spec/helpers/polyamorous_helper.rb +2 -8
- data/spec/helpers/ransack_helper.rb +1 -1
- data/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
- data/spec/{ransack → polyamorous}/join_association_spec.rb +3 -1
- data/spec/{ransack → polyamorous}/join_dependency_spec.rb +0 -16
- data/spec/ransack/adapters/active_record/base_spec.rb +125 -16
- data/spec/ransack/adapters/active_record/context_spec.rb +19 -18
- data/spec/ransack/configuration_spec.rb +33 -9
- data/spec/ransack/helpers/form_builder_spec.rb +8 -8
- data/spec/ransack/helpers/form_helper_spec.rb +109 -20
- data/spec/ransack/nodes/condition_spec.rb +37 -0
- data/spec/ransack/nodes/grouping_spec.rb +2 -2
- data/spec/ransack/nodes/value_spec.rb +115 -0
- data/spec/ransack/predicate_spec.rb +37 -2
- data/spec/ransack/search_spec.rb +238 -30
- data/spec/ransack/translate_spec.rb +1 -1
- data/spec/spec_helper.rb +7 -5
- data/spec/support/schema.rb +108 -11
- metadata +98 -62
- data/.travis.yml +0 -47
- data/lib/ransack/adapters/active_record/ransack/constants.rb +0 -128
- data/lib/ransack/adapters/active_record/ransack/context.rb +0 -55
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +0 -61
- 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/polyamorous/lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb +0 -20
- data/polyamorous/lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +0 -79
- data/polyamorous/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +0 -12
- data/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +0 -2
- data/polyamorous/lib/polyamorous/version.rb +0 -3
- data/polyamorous/polyamorous.gemspec +0 -27
- /data/{logo → docs/static/logo}/ransack-h.png +0 -0
- /data/{logo → docs/static/logo}/ransack-h.svg +0 -0
- /data/{logo → docs/static/logo}/ransack-v.png +0 -0
- /data/{logo → docs/static/logo}/ransack-v.svg +0 -0
- /data/{logo → docs/static/logo}/ransack.png +0 -0
- /data/{logo → docs/static/logo}/ransack.svg +0 -0
- /data/{polyamorous/lib → lib}/polyamorous/join.rb +0 -0
- /data/{polyamorous/lib → lib}/polyamorous/swapping_reflection_class.rb +0 -0
- /data/{polyamorous/lib → lib}/polyamorous/tree_node.rb +0 -0
- /data/lib/ransack/{adapters/active_record.rb → active_record.rb} +0 -0
- /data/spec/{ransack → polyamorous}/join_spec.rb +0 -0
|
@@ -20,7 +20,7 @@ module Ransack
|
|
|
20
20
|
Ransack.configure do |config|
|
|
21
21
|
config.add_predicate(
|
|
22
22
|
:test_predicate_without_compound,
|
|
23
|
-
:
|
|
23
|
+
compounds: false
|
|
24
24
|
)
|
|
25
25
|
end
|
|
26
26
|
expect(Ransack.predicates)
|
|
@@ -45,6 +45,20 @@ module Ransack
|
|
|
45
45
|
Ransack.options = default
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
it 'should have default value for strip_whitespace' do
|
|
49
|
+
expect(Ransack.options[:strip_whitespace]).to eq true
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'changes default search key parameter' do
|
|
53
|
+
default = Ransack.options.clone
|
|
54
|
+
|
|
55
|
+
Ransack.configure { |c| c.strip_whitespace = false }
|
|
56
|
+
|
|
57
|
+
expect(Ransack.options[:strip_whitespace]).to eq false
|
|
58
|
+
|
|
59
|
+
Ransack.options = default
|
|
60
|
+
end
|
|
61
|
+
|
|
48
62
|
it 'should have default values for arrows' do
|
|
49
63
|
expect(Ransack.options[:up_arrow]).to eq '▼'
|
|
50
64
|
expect(Ransack.options[:down_arrow]).to eq '▲'
|
|
@@ -124,8 +138,8 @@ module Ransack
|
|
|
124
138
|
Ransack.configure do |config|
|
|
125
139
|
config.add_predicate(
|
|
126
140
|
:test_array_predicate,
|
|
127
|
-
:
|
|
128
|
-
:
|
|
141
|
+
wants_array: true,
|
|
142
|
+
compounds: true
|
|
129
143
|
)
|
|
130
144
|
end
|
|
131
145
|
|
|
@@ -139,11 +153,11 @@ module Ransack
|
|
|
139
153
|
Ransack.configure do |config|
|
|
140
154
|
config.add_predicate(
|
|
141
155
|
:test_in_predicate,
|
|
142
|
-
:
|
|
156
|
+
arel_predicate: 'in'
|
|
143
157
|
)
|
|
144
158
|
config.add_predicate(
|
|
145
159
|
:test_not_in_predicate,
|
|
146
|
-
:
|
|
160
|
+
arel_predicate: 'not_in'
|
|
147
161
|
)
|
|
148
162
|
end
|
|
149
163
|
|
|
@@ -157,13 +171,13 @@ module Ransack
|
|
|
157
171
|
Ransack.configure do |config|
|
|
158
172
|
config.add_predicate(
|
|
159
173
|
:test_in_predicate_no_array,
|
|
160
|
-
:
|
|
161
|
-
:
|
|
174
|
+
arel_predicate: 'in',
|
|
175
|
+
wants_array: false
|
|
162
176
|
)
|
|
163
177
|
config.add_predicate(
|
|
164
178
|
:test_not_in_predicate_no_array,
|
|
165
|
-
:
|
|
166
|
-
:
|
|
179
|
+
arel_predicate: 'not_in',
|
|
180
|
+
wants_array: false
|
|
167
181
|
)
|
|
168
182
|
end
|
|
169
183
|
|
|
@@ -173,5 +187,15 @@ module Ransack
|
|
|
173
187
|
.to eq false
|
|
174
188
|
end
|
|
175
189
|
end
|
|
190
|
+
|
|
191
|
+
it "PG's sort option", if: ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" do
|
|
192
|
+
default = Ransack.options.clone
|
|
193
|
+
|
|
194
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_first }
|
|
195
|
+
|
|
196
|
+
expect(Ransack.options[:postgres_fields_sort_option]).to eq :nulls_first
|
|
197
|
+
|
|
198
|
+
Ransack.options = default
|
|
199
|
+
end
|
|
176
200
|
end
|
|
177
201
|
end
|
|
@@ -26,7 +26,7 @@ module Ransack
|
|
|
26
26
|
# @s.created_at_eq = date_values # This works in Rails 4.x but not 3.x
|
|
27
27
|
@s.created_at_eq = [2011, 1, 2, 3, 4, 5] # so we have to do this
|
|
28
28
|
html = @f.datetime_select(
|
|
29
|
-
:created_at_eq, :
|
|
29
|
+
:created_at_eq, use_month_numbers: true, include_seconds: true
|
|
30
30
|
)
|
|
31
31
|
date_values.each { |val| expect(html).to include date_select_html(val) }
|
|
32
32
|
end
|
|
@@ -70,13 +70,13 @@ module Ransack
|
|
|
70
70
|
|
|
71
71
|
describe '#sort_link' do
|
|
72
72
|
it 'sort_link for ransack attribute' do
|
|
73
|
-
sort_link = @f.sort_link :name, :
|
|
73
|
+
sort_link = @f.sort_link :name, controller: 'people'
|
|
74
74
|
expect(sort_link).to match /people\?q(%5B|\[)s(%5D|\])=name\+asc/
|
|
75
75
|
expect(sort_link).to match /sort_link/
|
|
76
76
|
expect(sort_link).to match /Full Name<\/a>/
|
|
77
77
|
end
|
|
78
78
|
it 'sort_link for common attribute' do
|
|
79
|
-
sort_link = @f.sort_link :id, :
|
|
79
|
+
sort_link = @f.sort_link :id, controller: 'people'
|
|
80
80
|
expect(sort_link).to match /id<\/a>/
|
|
81
81
|
end
|
|
82
82
|
end
|
|
@@ -99,14 +99,14 @@ module Ransack
|
|
|
99
99
|
it 'returns ransackable attributes for associations with :associations' do
|
|
100
100
|
attributes = Person.ransackable_attributes +
|
|
101
101
|
Article.ransackable_attributes.map { |a| "articles_#{a}" }
|
|
102
|
-
html = @f.attribute_select(:
|
|
102
|
+
html = @f.attribute_select(associations: ['articles'])
|
|
103
103
|
expect(html.split(/\n/).size).to eq(attributes.size)
|
|
104
104
|
attributes.each do |attribute|
|
|
105
105
|
expect(html).to match /<option value="#{attribute}">/
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
it 'returns option groups for base and associations with :associations' do
|
|
109
|
-
html = @f.attribute_select(:
|
|
109
|
+
html = @f.attribute_select(associations: ['articles'])
|
|
110
110
|
[Person, Article].each do |model|
|
|
111
111
|
expect(html).to match /<optgroup label="#{model}">/
|
|
112
112
|
end
|
|
@@ -121,19 +121,19 @@ module Ransack
|
|
|
121
121
|
end
|
|
122
122
|
end
|
|
123
123
|
it 'filters predicates with single-value :only' do
|
|
124
|
-
html = @f.predicate_select :
|
|
124
|
+
html = @f.predicate_select only: 'eq'
|
|
125
125
|
Predicate.names.reject { |k| k =~ /^eq/ }.each do |key|
|
|
126
126
|
expect(html).not_to match /<option value="#{key}">/
|
|
127
127
|
end
|
|
128
128
|
end
|
|
129
129
|
it 'filters predicates with multi-value :only' do
|
|
130
|
-
html = @f.predicate_select :
|
|
130
|
+
html = @f.predicate_select only: [:eq, :lt]
|
|
131
131
|
Predicate.names.reject { |k| k =~ /^(eq|lt)/ }.each do |key|
|
|
132
132
|
expect(html).not_to match /<option value="#{key}">/
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
135
|
it 'excludes compounds when compounds: false' do
|
|
136
|
-
html = @f.predicate_select :
|
|
136
|
+
html = @f.predicate_select compounds: false
|
|
137
137
|
Predicate.names.select { |k| k =~ /_(any|all)$/ }.each do |key|
|
|
138
138
|
expect(html).not_to match /<option value="#{key}">/
|
|
139
139
|
end
|
|
@@ -140,6 +140,32 @@ module Ransack
|
|
|
140
140
|
}
|
|
141
141
|
end
|
|
142
142
|
|
|
143
|
+
describe '#sort_link works even if search params are a string' do
|
|
144
|
+
before { @controller.view_context.params[:q] = 'input error' }
|
|
145
|
+
specify {
|
|
146
|
+
expect { @controller.view_context
|
|
147
|
+
.sort_link(
|
|
148
|
+
Person.ransack({}),
|
|
149
|
+
:name,
|
|
150
|
+
controller: 'people'
|
|
151
|
+
)
|
|
152
|
+
}.not_to raise_error
|
|
153
|
+
}
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
describe '#sort_url works even if search params are a string' do
|
|
157
|
+
before { @controller.view_context.params[:q] = 'input error' }
|
|
158
|
+
specify {
|
|
159
|
+
expect { @controller.view_context
|
|
160
|
+
.sort_url(
|
|
161
|
+
Person.ransack({}),
|
|
162
|
+
:name,
|
|
163
|
+
controller: 'people'
|
|
164
|
+
)
|
|
165
|
+
}.not_to raise_error
|
|
166
|
+
}
|
|
167
|
+
end
|
|
168
|
+
|
|
143
169
|
describe '#sort_link with search_key defined as a string' do
|
|
144
170
|
subject { @controller.view_context
|
|
145
171
|
.sort_link(
|
|
@@ -186,7 +212,7 @@ module Ransack
|
|
|
186
212
|
)
|
|
187
213
|
}
|
|
188
214
|
it {
|
|
189
|
-
should match(
|
|
215
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+asc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
190
216
|
)
|
|
191
217
|
}
|
|
192
218
|
it { should match /sort_link desc/ }
|
|
@@ -202,7 +228,7 @@ module Ransack
|
|
|
202
228
|
)
|
|
203
229
|
}
|
|
204
230
|
it {
|
|
205
|
-
should match(
|
|
231
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+asc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
206
232
|
)
|
|
207
233
|
}
|
|
208
234
|
end
|
|
@@ -216,7 +242,7 @@ module Ransack
|
|
|
216
242
|
)
|
|
217
243
|
}
|
|
218
244
|
it {
|
|
219
|
-
should match(
|
|
245
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+asc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
220
246
|
)
|
|
221
247
|
}
|
|
222
248
|
it { should match /sort_link desc/ }
|
|
@@ -232,7 +258,7 @@ module Ransack
|
|
|
232
258
|
)
|
|
233
259
|
}
|
|
234
260
|
it {
|
|
235
|
-
should match(
|
|
261
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+asc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
236
262
|
)
|
|
237
263
|
}
|
|
238
264
|
end
|
|
@@ -258,7 +284,7 @@ module Ransack
|
|
|
258
284
|
)
|
|
259
285
|
}
|
|
260
286
|
it {
|
|
261
|
-
should match(
|
|
287
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+asc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
262
288
|
)
|
|
263
289
|
}
|
|
264
290
|
it { should match /sort_link desc/ }
|
|
@@ -274,7 +300,7 @@ module Ransack
|
|
|
274
300
|
)
|
|
275
301
|
}
|
|
276
302
|
it {
|
|
277
|
-
should match(
|
|
303
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+asc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
278
304
|
)
|
|
279
305
|
}
|
|
280
306
|
end
|
|
@@ -289,7 +315,7 @@ module Ransack
|
|
|
289
315
|
)
|
|
290
316
|
}
|
|
291
317
|
it {
|
|
292
|
-
should match(
|
|
318
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+desc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
293
319
|
)
|
|
294
320
|
}
|
|
295
321
|
it { should match /sort_link/ }
|
|
@@ -306,7 +332,7 @@ module Ransack
|
|
|
306
332
|
)
|
|
307
333
|
}
|
|
308
334
|
it {
|
|
309
|
-
should match(
|
|
335
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+desc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
310
336
|
)
|
|
311
337
|
}
|
|
312
338
|
end
|
|
@@ -321,7 +347,7 @@ module Ransack
|
|
|
321
347
|
)
|
|
322
348
|
}
|
|
323
349
|
it {
|
|
324
|
-
should match(
|
|
350
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+desc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
325
351
|
)
|
|
326
352
|
}
|
|
327
353
|
it { should match /sort_link/ }
|
|
@@ -338,7 +364,7 @@ module Ransack
|
|
|
338
364
|
)
|
|
339
365
|
}
|
|
340
366
|
it {
|
|
341
|
-
should match(
|
|
367
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+desc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
342
368
|
)
|
|
343
369
|
}
|
|
344
370
|
end
|
|
@@ -353,7 +379,7 @@ module Ransack
|
|
|
353
379
|
)
|
|
354
380
|
}
|
|
355
381
|
it {
|
|
356
|
-
should match(
|
|
382
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+desc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+asc/
|
|
357
383
|
)
|
|
358
384
|
}
|
|
359
385
|
it { should match /sort_link/ }
|
|
@@ -370,7 +396,7 @@ module Ransack
|
|
|
370
396
|
)
|
|
371
397
|
}
|
|
372
398
|
it {
|
|
373
|
-
should match(
|
|
399
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+desc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+asc/
|
|
374
400
|
)
|
|
375
401
|
}
|
|
376
402
|
end
|
|
@@ -385,7 +411,7 @@ module Ransack
|
|
|
385
411
|
)
|
|
386
412
|
}
|
|
387
413
|
it {
|
|
388
|
-
should match(
|
|
414
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+desc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
389
415
|
)
|
|
390
416
|
}
|
|
391
417
|
it { should match /sort_link/ }
|
|
@@ -402,7 +428,7 @@ module Ransack
|
|
|
402
428
|
)
|
|
403
429
|
}
|
|
404
430
|
it {
|
|
405
|
-
should match(
|
|
431
|
+
should match(/people\?q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=name\+desc&q(%5B|\[)s(%5D|\])(%5B|\[)(%5D|\])=email\+desc/
|
|
406
432
|
)
|
|
407
433
|
}
|
|
408
434
|
end
|
|
@@ -469,13 +495,12 @@ module Ransack
|
|
|
469
495
|
it { should match /exist\=existing/ }
|
|
470
496
|
end
|
|
471
497
|
|
|
472
|
-
context 'using a real ActionController::Parameter object'
|
|
473
|
-
if: ::ActiveRecord::VERSION::MAJOR > 3 do
|
|
498
|
+
context 'using a real ActionController::Parameter object' do
|
|
474
499
|
|
|
475
500
|
describe 'with symbol q:, #sort_link should include search params' do
|
|
476
501
|
subject { @controller.view_context.sort_link(Person.ransack, :name) }
|
|
477
502
|
let(:params) { ActionController::Parameters.new(
|
|
478
|
-
{ :
|
|
503
|
+
{ q: { name_eq: 'TEST' }, controller: 'people' }
|
|
479
504
|
) }
|
|
480
505
|
before { @controller.instance_variable_set(:@params, params) }
|
|
481
506
|
|
|
@@ -490,7 +515,7 @@ module Ransack
|
|
|
490
515
|
describe 'with symbol q:, #sort_url should include search params' do
|
|
491
516
|
subject { @controller.view_context.sort_url(Person.ransack, :name) }
|
|
492
517
|
let(:params) { ActionController::Parameters.new(
|
|
493
|
-
{ :
|
|
518
|
+
{ q: { name_eq: 'TEST' }, controller: 'people' }
|
|
494
519
|
) }
|
|
495
520
|
before { @controller.instance_variable_set(:@params, params) }
|
|
496
521
|
|
|
@@ -643,13 +668,13 @@ module Ransack
|
|
|
643
668
|
before do
|
|
644
669
|
Ransack.configure do |c|
|
|
645
670
|
c.hide_sort_order_indicators = false
|
|
646
|
-
c.custom_arrows = { default_arrow: "defaultarrow"}
|
|
671
|
+
c.custom_arrows = { default_arrow: "defaultarrow" }
|
|
647
672
|
end
|
|
648
673
|
end
|
|
649
674
|
|
|
650
675
|
after do
|
|
651
676
|
Ransack.configure do |c|
|
|
652
|
-
c.custom_arrows = { default_arrow: nil}
|
|
677
|
+
c.custom_arrows = { default_arrow: nil }
|
|
653
678
|
end
|
|
654
679
|
end
|
|
655
680
|
|
|
@@ -727,6 +752,70 @@ module Ransack
|
|
|
727
752
|
it { should match /Block label ▼/ }
|
|
728
753
|
end
|
|
729
754
|
|
|
755
|
+
describe '#sort_link with class option' do
|
|
756
|
+
subject { @controller.view_context
|
|
757
|
+
.sort_link(
|
|
758
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
|
759
|
+
:name,
|
|
760
|
+
class: 'people', controller: 'people'
|
|
761
|
+
)
|
|
762
|
+
}
|
|
763
|
+
it { should match /class="sort_link desc people"/ }
|
|
764
|
+
it { should_not match /people\?class=people/ }
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
describe '#sort_link with class option workaround' do
|
|
768
|
+
it "generates a correct link and prints a deprecation" do
|
|
769
|
+
expect do
|
|
770
|
+
link = @controller.view_context
|
|
771
|
+
.sort_link(
|
|
772
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
|
773
|
+
:name,
|
|
774
|
+
'name',
|
|
775
|
+
{ controller: 'people' },
|
|
776
|
+
class: 'people'
|
|
777
|
+
)
|
|
778
|
+
|
|
779
|
+
expect(link).to match(/class="sort_link desc people"/)
|
|
780
|
+
expect(link).not_to match(/people\?class=people/)
|
|
781
|
+
end.to output(
|
|
782
|
+
/Passing two trailing hashes to `sort_link` is deprecated, merge the trailing hashes into a single one\. \(called at #{Regexp.escape(__FILE__)}:/
|
|
783
|
+
).to_stderr
|
|
784
|
+
end
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
describe '#sort_link with data option' do
|
|
788
|
+
subject { @controller.view_context
|
|
789
|
+
.sort_link(
|
|
790
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
|
791
|
+
:name,
|
|
792
|
+
data: { turbo_action: :advance }, controller: 'people'
|
|
793
|
+
)
|
|
794
|
+
}
|
|
795
|
+
it { should match /data-turbo-action="advance"/ }
|
|
796
|
+
it { should_not match /people\?data%5Bturbo_action%5D=advance/ }
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
describe "#sort_link with host option" do
|
|
800
|
+
subject { @controller.view_context
|
|
801
|
+
.sort_link(
|
|
802
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
|
803
|
+
:name,
|
|
804
|
+
host: 'foo', controller: 'people'
|
|
805
|
+
)
|
|
806
|
+
}
|
|
807
|
+
it { should match /href="\/people\?q/ }
|
|
808
|
+
it { should_not match /href=".*foo/ }
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
describe "#sort_link ignores host in params" do
|
|
812
|
+
before { @controller.view_context.params[:host] = 'other_domain' }
|
|
813
|
+
subject { @controller.view_context.sort_link(Person.ransack, :name, controller: 'people') }
|
|
814
|
+
|
|
815
|
+
it { should match /href="\/people\?q/ }
|
|
816
|
+
it { should_not match /href=".*other_domain/ }
|
|
817
|
+
end
|
|
818
|
+
|
|
730
819
|
describe '#search_form_for with default format' do
|
|
731
820
|
subject { @controller.view_context
|
|
732
821
|
.search_form_for(Person.ransack) {} }
|
|
@@ -3,6 +3,19 @@ require 'spec_helper'
|
|
|
3
3
|
module Ransack
|
|
4
4
|
module Nodes
|
|
5
5
|
describe Condition do
|
|
6
|
+
context 'bug report #1245' do
|
|
7
|
+
it 'preserves tuple behavior' do
|
|
8
|
+
ransack_hash = {
|
|
9
|
+
m: 'and',
|
|
10
|
+
g: [
|
|
11
|
+
{ title_type_in: ['["title 1", ""]'] }
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
sql = Article.ransack(ransack_hash).result.to_sql
|
|
16
|
+
expect(sql).to include("IN (('title 1', ''))")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
6
19
|
|
|
7
20
|
context 'with an alias' do
|
|
8
21
|
subject {
|
|
@@ -61,6 +74,30 @@ module Ransack
|
|
|
61
74
|
specify { expect(subject).to be_nil }
|
|
62
75
|
end
|
|
63
76
|
end
|
|
77
|
+
|
|
78
|
+
context 'with an empty predicate' do
|
|
79
|
+
subject {
|
|
80
|
+
Condition.extract(
|
|
81
|
+
Context.for(Person), 'full_name', Person.first.name
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
context "when default_predicate = nil" do
|
|
86
|
+
before do
|
|
87
|
+
Ransack.configure { |c| c.default_predicate = nil }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
specify { expect(subject).to be_nil }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context "when default_predicate = 'eq'" do
|
|
94
|
+
before do
|
|
95
|
+
Ransack.configure { |c| c.default_predicate = 'eq' }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
specify { expect(subject).to eq Condition.extract(Context.for(Person), 'full_name_eq', Person.first.name) }
|
|
99
|
+
end
|
|
100
|
+
end
|
|
64
101
|
end
|
|
65
102
|
end
|
|
66
103
|
end
|
|
@@ -80,7 +80,7 @@ module Ransack
|
|
|
80
80
|
'a' => {
|
|
81
81
|
'0' => {
|
|
82
82
|
'name' => 'with_arguments',
|
|
83
|
-
'ransacker_args' => [1,2]
|
|
83
|
+
'ransacker_args' => [1, 2]
|
|
84
84
|
}
|
|
85
85
|
},
|
|
86
86
|
'p' => 'eq',
|
|
@@ -90,7 +90,7 @@ module Ransack
|
|
|
90
90
|
'a' => {
|
|
91
91
|
'0' => {
|
|
92
92
|
'name' => 'with_arguments',
|
|
93
|
-
'ransacker_args' => [3,4]
|
|
93
|
+
'ransacker_args' => [3, 4]
|
|
94
94
|
}
|
|
95
95
|
},
|
|
96
96
|
'p' => 'eq',
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Ransack
|
|
4
|
+
module Nodes
|
|
5
|
+
describe Value do
|
|
6
|
+
let(:context) { Context.for(Person) }
|
|
7
|
+
|
|
8
|
+
subject do
|
|
9
|
+
Value.new(context, raw_value)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context "with a date value" do
|
|
13
|
+
let(:raw_value) { "2022-05-23" }
|
|
14
|
+
|
|
15
|
+
[:date].each do |type|
|
|
16
|
+
it "should cast #{type} correctly" do
|
|
17
|
+
result = subject.cast(type)
|
|
18
|
+
|
|
19
|
+
expect(result).to be_a_kind_of(Date)
|
|
20
|
+
expect(result).to eq(Date.parse(raw_value))
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context "with a timestamp value" do
|
|
26
|
+
let(:raw_value) { "2022-05-23 10:40:02 -0400" }
|
|
27
|
+
|
|
28
|
+
[:datetime, :timestamp, :time, :timestamptz].each do |type|
|
|
29
|
+
it "should cast #{type} correctly" do
|
|
30
|
+
result = subject.cast(type)
|
|
31
|
+
|
|
32
|
+
expect(result).to be_a_kind_of(Time)
|
|
33
|
+
expect(result).to eq(Time.zone.parse(raw_value))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
Constants::TRUE_VALUES.each do |value|
|
|
39
|
+
context "with a true boolean value (#{value})" do
|
|
40
|
+
let(:raw_value) { value.to_s }
|
|
41
|
+
|
|
42
|
+
it "should cast boolean correctly" do
|
|
43
|
+
result = subject.cast(:boolean)
|
|
44
|
+
expect(result).to eq(true)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
Constants::FALSE_VALUES.each do |value|
|
|
50
|
+
context "with a false boolean value (#{value})" do
|
|
51
|
+
let(:raw_value) { value.to_s }
|
|
52
|
+
|
|
53
|
+
it "should cast boolean correctly" do
|
|
54
|
+
result = subject.cast(:boolean)
|
|
55
|
+
|
|
56
|
+
expect(result).to eq(false)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
["12", "101.5"].each do |value|
|
|
62
|
+
context "with an integer value (#{value})" do
|
|
63
|
+
let(:raw_value) { value }
|
|
64
|
+
|
|
65
|
+
it "should cast #{value} to integer correctly" do
|
|
66
|
+
result = subject.cast(:integer)
|
|
67
|
+
|
|
68
|
+
expect(result).to be_an(Integer)
|
|
69
|
+
expect(result).to eq(value.to_i)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
["12", "101.5"].each do |value|
|
|
75
|
+
context "with a float value (#{value})" do
|
|
76
|
+
let(:raw_value) { value }
|
|
77
|
+
|
|
78
|
+
it "should cast #{value} to float correctly" do
|
|
79
|
+
result = subject.cast(:float)
|
|
80
|
+
|
|
81
|
+
expect(result).to be_an(Float)
|
|
82
|
+
expect(result).to eq(value.to_f)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
["12", "101.5"].each do |value|
|
|
88
|
+
context "with a decimal value (#{value})" do
|
|
89
|
+
let(:raw_value) { value }
|
|
90
|
+
|
|
91
|
+
it "should cast #{value} to decimal correctly" do
|
|
92
|
+
result = subject.cast(:decimal)
|
|
93
|
+
|
|
94
|
+
expect(result).to be_a(BigDecimal)
|
|
95
|
+
expect(result).to eq(value.to_d)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
["12", "101.513"].each do |value|
|
|
101
|
+
context "with a money value (#{value})" do
|
|
102
|
+
let(:raw_value) { value }
|
|
103
|
+
|
|
104
|
+
it "should cast #{value} to money correctly" do
|
|
105
|
+
result = subject.cast(:money)
|
|
106
|
+
|
|
107
|
+
expect(result).to be_a(String)
|
|
108
|
+
expect(result).to eq(value.to_f.to_s)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -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
|
|
@@ -422,7 +457,7 @@ module Ransack
|
|
|
422
457
|
context "defining custom predicates" do
|
|
423
458
|
describe "with 'not_in' arel predicate" do
|
|
424
459
|
before do
|
|
425
|
-
Ransack.configure {|c| c.add_predicate "not_in_csv", arel_predicate: "not_in", formatter: proc { |v| v.split(",") } }
|
|
460
|
+
Ransack.configure { |c| c.add_predicate "not_in_csv", arel_predicate: "not_in", formatter: proc { |v| v.split(",") } }
|
|
426
461
|
end
|
|
427
462
|
|
|
428
463
|
it 'generates a value IS NOT NULL query' do
|