ransack 2.3.0 → 4.1.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/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 +263 -1
- data/CONTRIBUTING.md +51 -29
- data/Gemfile +24 -10
- data/README.md +49 -917
- 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_6.1_ruby_2/join_association.rb +70 -0
- data/{polyamorous/lib/polyamorous/activerecord_6.0_ruby_2 → lib/polyamorous/activerecord_6.1_ruby_2}/join_dependency.rb +33 -12
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/reflection.rb +1 -0
- data/{polyamorous/lib → lib/polyamorous}/polyamorous.rb +3 -8
- data/lib/ransack/adapters/active_record/base.rb +83 -10
- data/lib/ransack/adapters/active_record/context.rb +61 -116
- data/lib/ransack/configuration.rb +53 -10
- data/lib/ransack/constants.rb +126 -7
- data/lib/ransack/context.rb +34 -5
- data/lib/ransack/helpers/form_builder.rb +11 -17
- data/lib/ransack/helpers/form_helper.rb +14 -5
- data/lib/ransack/helpers.rb +1 -1
- data/lib/ransack/locale/sk.yml +70 -0
- data/lib/ransack/locale/sv.yml +70 -0
- data/lib/ransack/nodes/attribute.rb +3 -3
- data/lib/ransack/nodes/condition.rb +87 -8
- 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 +3 -2
- 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 +6 -10
- data/ransack.gemspec +9 -24
- 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 -17
- 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 +75 -2
- data/spec/ransack/search_spec.rb +239 -38
- data/spec/ransack/translate_spec.rb +1 -1
- data/spec/spec_helper.rb +9 -5
- data/spec/support/schema.rb +111 -12
- metadata +105 -195
- data/.travis.yml +0 -49
- data/lib/ransack/adapters/active_record/ransack/constants.rb +0 -116
- data/lib/ransack/adapters/active_record/ransack/context.rb +0 -60
- 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.0_ruby_2/join_association.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +0 -31
- data/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +0 -112
- data/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb +0 -31
- data/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +0 -112
- data/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb +0 -12
- data/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb +0 -22
- data/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb +0 -81
- data/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/reflection.rb +0 -2
- 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 -35
- /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
|
@@ -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
|
|
@@ -159,6 +194,44 @@ module Ransack
|
|
|
159
194
|
end
|
|
160
195
|
end
|
|
161
196
|
|
|
197
|
+
describe 'i_cont' do
|
|
198
|
+
it_has_behavior 'wildcard escaping', :name_i_cont,
|
|
199
|
+
(if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
|
|
200
|
+
/"people"."name" ILIKE '%\\%\\.\\_\\\\%'/
|
|
201
|
+
elsif ActiveRecord::Base.connection.adapter_name == "Mysql2"
|
|
202
|
+
/LOWER\(`people`.`name`\) LIKE '%\\\\%.\\\\_\\\\\\\\%'/
|
|
203
|
+
else
|
|
204
|
+
/LOWER\("people"."name"\) LIKE '%%._\\%'/
|
|
205
|
+
end) do
|
|
206
|
+
subject { @s }
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it 'generates a LIKE query with LOWER(column) and value surrounded by %' do
|
|
210
|
+
@s.name_i_cont = 'Ric'
|
|
211
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
212
|
+
expect(@s.result.to_sql).to match /[LOWER\(]?#{field}\)? I?LIKE '%ric%'/
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
describe 'not_i_cont' do
|
|
217
|
+
it_has_behavior 'wildcard escaping', :name_not_i_cont,
|
|
218
|
+
(if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
|
|
219
|
+
/"people"."name" NOT ILIKE '%\\%\\.\\_\\\\%'/
|
|
220
|
+
elsif ActiveRecord::Base.connection.adapter_name == "Mysql2"
|
|
221
|
+
/LOWER\(`people`.`name`\) NOT LIKE '%\\\\%.\\\\_\\\\\\\\%'/
|
|
222
|
+
else
|
|
223
|
+
/LOWER\("people"."name"\) NOT LIKE '%%._\\%'/
|
|
224
|
+
end) do
|
|
225
|
+
subject { @s }
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it 'generates a NOT LIKE query with LOWER(column) and value surrounded by %' do
|
|
229
|
+
@s.name_not_i_cont = 'Ric'
|
|
230
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("name")}"
|
|
231
|
+
expect(@s.result.to_sql).to match /[LOWER\(]?#{field}\)? NOT I?LIKE '%ric%'/
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
162
235
|
describe 'start' do
|
|
163
236
|
it 'generates a LIKE query with value followed by %' do
|
|
164
237
|
@s.name_start = 'Er'
|
|
@@ -330,7 +403,7 @@ module Ransack
|
|
|
330
403
|
expect(@s.result.to_sql).to match /#{field} IS NULL/
|
|
331
404
|
end
|
|
332
405
|
|
|
333
|
-
describe 'with association
|
|
406
|
+
describe 'with association query' do
|
|
334
407
|
it 'generates a value IS NOT NULL query' do
|
|
335
408
|
@s.comments_id_not_null = true
|
|
336
409
|
sql = @s.result.to_sql
|
|
@@ -384,7 +457,7 @@ module Ransack
|
|
|
384
457
|
context "defining custom predicates" do
|
|
385
458
|
describe "with 'not_in' arel predicate" do
|
|
386
459
|
before do
|
|
387
|
-
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(",") } }
|
|
388
461
|
end
|
|
389
462
|
|
|
390
463
|
it 'generates a value IS NOT NULL query' do
|