ransack 2.4.2 → 3.2.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/cronjob.yml +6 -9
- data/.github/workflows/deploy.yml +35 -0
- data/.github/workflows/rubocop.yml +1 -1
- data/.github/workflows/test-deploy.yml +29 -0
- data/.github/workflows/test.yml +16 -40
- data/.nojekyll +0 -0
- data/CHANGELOG.md +137 -11
- data/CONTRIBUTING.md +4 -3
- data/Gemfile +2 -2
- data/README.md +45 -973
- 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 +284 -0
- data/docs/docs/getting-started/sorting.md +79 -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/merging-searches.md +41 -0
- data/docs/docs/going-further/other-notes.md +428 -0
- data/docs/docs/going-further/polymorphic-search.md +40 -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 +107 -0
- data/docs/package.json +37 -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 +7671 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +0 -4
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +0 -1
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -1
- 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/lib/polyamorous.rb +1 -0
- data/lib/ransack/adapters/active_record/base.rb +1 -3
- data/lib/ransack/adapters/active_record/context.rb +24 -51
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +2 -9
- data/lib/ransack/configuration.rb +16 -2
- data/lib/ransack/constants.rb +0 -3
- data/lib/ransack/helpers/form_helper.rb +11 -3
- data/lib/ransack/locale/sv.yml +70 -0
- data/lib/ransack/nodes/sort.rb +2 -2
- data/lib/ransack/search.rb +4 -3
- data/lib/ransack/translate.rb +1 -1
- data/lib/ransack/version.rb +1 -1
- data/ransack.gemspec +5 -5
- data/spec/helpers/polyamorous_helper.rb +2 -8
- data/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
- data/spec/polyamorous/join_association_spec.rb +1 -6
- data/spec/polyamorous/join_dependency_spec.rb +0 -16
- data/spec/ransack/adapters/active_record/base_spec.rb +28 -11
- data/spec/ransack/configuration_spec.rb +14 -0
- data/spec/ransack/helpers/form_helper_spec.rb +57 -2
- data/spec/ransack/nodes/condition_spec.rb +13 -0
- data/spec/ransack/search_spec.rb +140 -27
- data/spec/support/schema.rb +49 -0
- metadata +80 -29
- data/docs/release_process.md +0 -20
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb +0 -24
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +0 -79
- data/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +0 -11
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +0 -1
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +0 -80
- data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +0 -1
- /data/docs/{img → docs/going-further/img}/create_release.png +0 -0
- /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/lib/polyamorous/{activerecord_6.2_ruby_2 → activerecord_7.0_ruby_2}/join_association.rb +0 -0
- /data/lib/polyamorous/{activerecord_6.2_ruby_2 → activerecord_7.0_ruby_2}/join_dependency.rb +0 -0
- /data/lib/polyamorous/{activerecord_6.2_ruby_2 → activerecord_7.0_ruby_2}/reflection.rb +0 -0
|
@@ -469,8 +469,7 @@ module Ransack
|
|
|
469
469
|
it { should match /exist\=existing/ }
|
|
470
470
|
end
|
|
471
471
|
|
|
472
|
-
context 'using a real ActionController::Parameter object'
|
|
473
|
-
if: ::ActiveRecord::VERSION::MAJOR > 3 do
|
|
472
|
+
context 'using a real ActionController::Parameter object' do
|
|
474
473
|
|
|
475
474
|
describe 'with symbol q:, #sort_link should include search params' do
|
|
476
475
|
subject { @controller.view_context.sort_link(Person.ransack, :name) }
|
|
@@ -727,6 +726,62 @@ module Ransack
|
|
|
727
726
|
it { should match /Block label ▼/ }
|
|
728
727
|
end
|
|
729
728
|
|
|
729
|
+
describe '#sort_link with class option' do
|
|
730
|
+
subject { @controller.view_context
|
|
731
|
+
.sort_link(
|
|
732
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
|
733
|
+
:name,
|
|
734
|
+
class: 'people', controller: 'people'
|
|
735
|
+
)
|
|
736
|
+
}
|
|
737
|
+
it { should match /class="sort_link desc people"/ }
|
|
738
|
+
it { should_not match /people\?class=people/ }
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
describe '#sort_link with class option workaround' do
|
|
742
|
+
it "generates a correct link and prints a deprecation" do
|
|
743
|
+
expect do
|
|
744
|
+
link = @controller.view_context
|
|
745
|
+
.sort_link(
|
|
746
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
|
747
|
+
:name,
|
|
748
|
+
'name',
|
|
749
|
+
{ controller: 'people' },
|
|
750
|
+
class: 'people'
|
|
751
|
+
)
|
|
752
|
+
|
|
753
|
+
expect(link).to match(/class="sort_link desc people"/)
|
|
754
|
+
expect(link).not_to match(/people\?class=people/)
|
|
755
|
+
end.to output(
|
|
756
|
+
/Passing two trailing hashes to `sort_link` is deprecated, merge the trailing hashes into a single one\. \(called at #{Regexp.escape(__FILE__)}:/
|
|
757
|
+
).to_stderr
|
|
758
|
+
end
|
|
759
|
+
end
|
|
760
|
+
|
|
761
|
+
describe '#sort_link with data option' do
|
|
762
|
+
subject { @controller.view_context
|
|
763
|
+
.sort_link(
|
|
764
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
|
765
|
+
:name,
|
|
766
|
+
data: { turbo_action: :advance }, controller: 'people'
|
|
767
|
+
)
|
|
768
|
+
}
|
|
769
|
+
it { should match /data-turbo-action="advance"/ }
|
|
770
|
+
it { should_not match /people\?data%5Bturbo_action%5D=advance/ }
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
describe "#sort_link with host option" do
|
|
774
|
+
subject { @controller.view_context
|
|
775
|
+
.sort_link(
|
|
776
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
|
777
|
+
:name,
|
|
778
|
+
host: 'foo', controller: 'people'
|
|
779
|
+
)
|
|
780
|
+
}
|
|
781
|
+
it { should match /href="\/people\?q/ }
|
|
782
|
+
it { should_not match /href=".*foo/ }
|
|
783
|
+
end
|
|
784
|
+
|
|
730
785
|
describe '#search_form_for with default format' do
|
|
731
786
|
subject { @controller.view_context
|
|
732
787
|
.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 {
|
data/spec/ransack/search_spec.rb
CHANGED
|
@@ -20,10 +20,42 @@ module Ransack
|
|
|
20
20
|
Search.new(Person, name_eq: 'foobar')
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
context 'whitespace stripping' do
|
|
24
|
+
context 'when whitespace_strip option is true' do
|
|
25
|
+
before do
|
|
26
|
+
Ransack.configure { |c| c.strip_whitespace = true }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'strips leading & trailing whitespace before building' do
|
|
30
|
+
expect_any_instance_of(Search).to receive(:build)
|
|
31
|
+
.with({ 'name_eq' => 'foobar' })
|
|
32
|
+
Search.new(Person, name_eq: ' foobar ')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'when whitespace_strip option is false' do
|
|
37
|
+
before do
|
|
38
|
+
Ransack.configure { |c| c.strip_whitespace = false }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'doesn\'t strip leading & trailing whitespace before building' do
|
|
42
|
+
expect_any_instance_of(Search).to receive(:build)
|
|
43
|
+
.with({ 'name_eq' => ' foobar ' })
|
|
44
|
+
Search.new(Person, name_eq: ' foobar ')
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'strips leading & trailing whitespace when strip_whitespace search parameter is true' do
|
|
49
|
+
expect_any_instance_of(Search).to receive(:build)
|
|
50
|
+
.with({ 'name_eq' => 'foobar' })
|
|
51
|
+
Search.new(Person, { name_eq: ' foobar ' }, { strip_whitespace: true })
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'doesn\'t strip leading & trailing whitespace when strip_whitespace search parameter is false' do
|
|
55
|
+
expect_any_instance_of(Search).to receive(:build)
|
|
56
|
+
.with({ 'name_eq' => ' foobar ' })
|
|
57
|
+
Search.new(Person, { name_eq: ' foobar ' }, { strip_whitespace: false })
|
|
58
|
+
end
|
|
27
59
|
end
|
|
28
60
|
|
|
29
61
|
it 'removes empty suffixed conditions before building' do
|
|
@@ -280,6 +312,29 @@ module Ransack
|
|
|
280
312
|
expect { Search.new(Person, params) }.not_to change { params }
|
|
281
313
|
end
|
|
282
314
|
|
|
315
|
+
context "ransackable_scope" do
|
|
316
|
+
around(:each) do |example|
|
|
317
|
+
Person.define_singleton_method(:name_eq) do |name|
|
|
318
|
+
self.where(name: name)
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
begin
|
|
322
|
+
example.run
|
|
323
|
+
ensure
|
|
324
|
+
Person.singleton_class.undef_method :name_eq
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it "is prioritized over base predicates" do
|
|
329
|
+
allow(Person).to receive(:ransackable_scopes)
|
|
330
|
+
.and_return(Person.ransackable_scopes + [:name_eq])
|
|
331
|
+
|
|
332
|
+
s = Search.new(Person, name_eq: "Johny")
|
|
333
|
+
expect(s.instance_variable_get(:@scope_args)["name_eq"]).to eq("Johny")
|
|
334
|
+
expect(s.base[:name_eq]).to be_nil
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
283
338
|
end
|
|
284
339
|
|
|
285
340
|
describe '#result' do
|
|
@@ -300,8 +355,6 @@ module Ransack
|
|
|
300
355
|
end
|
|
301
356
|
|
|
302
357
|
it 'use appropriate table alias' do
|
|
303
|
-
skip "Rails 6 regressed here, but it's fixed in 6-0-stable since https://github.com/rails/rails/commit/f9ba52477ca288e7effa5f6794ae3df3f4e982bc" if ENV["RAILS"] == "v6.0.3"
|
|
304
|
-
|
|
305
358
|
s = Search.new(Person, {
|
|
306
359
|
name_eq: "person_name_query",
|
|
307
360
|
articles_title_eq: "person_article_title_query",
|
|
@@ -451,82 +504,109 @@ module Ransack
|
|
|
451
504
|
expect(sort.dir).to eq 'asc'
|
|
452
505
|
end
|
|
453
506
|
|
|
454
|
-
it 'creates sorts based on
|
|
455
|
-
@s.sorts =
|
|
507
|
+
it 'creates sorts based on a single alias/direction' do
|
|
508
|
+
@s.sorts = 'daddy desc'
|
|
509
|
+
expect(@s.sorts.size).to eq(1)
|
|
510
|
+
sort = @s.sorts.first
|
|
511
|
+
expect(sort).to be_a Nodes::Sort
|
|
512
|
+
expect(sort.name).to eq 'parent_name'
|
|
513
|
+
expect(sort.dir).to eq 'desc'
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
it 'creates sorts based on a single alias and uppercase direction' do
|
|
517
|
+
@s.sorts = 'daddy DESC'
|
|
518
|
+
expect(@s.sorts.size).to eq(1)
|
|
519
|
+
sort = @s.sorts.first
|
|
520
|
+
expect(sort).to be_a Nodes::Sort
|
|
521
|
+
expect(sort.name).to eq 'parent_name'
|
|
522
|
+
expect(sort.dir).to eq 'desc'
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
it 'creates sorts based on a single alias and without direction' do
|
|
526
|
+
@s.sorts = 'daddy'
|
|
527
|
+
expect(@s.sorts.size).to eq(1)
|
|
528
|
+
sort = @s.sorts.first
|
|
529
|
+
expect(sort).to be_a Nodes::Sort
|
|
530
|
+
expect(sort.name).to eq 'parent_name'
|
|
531
|
+
expect(sort.dir).to eq 'asc'
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
it 'creates sorts based on attributes, alias and directions in array format' do
|
|
535
|
+
@s.sorts = ['id desc', { name: 'daddy', dir: 'asc' }]
|
|
456
536
|
expect(@s.sorts.size).to eq(2)
|
|
457
537
|
sort1, sort2 = @s.sorts
|
|
458
538
|
expect(sort1).to be_a Nodes::Sort
|
|
459
539
|
expect(sort1.name).to eq 'id'
|
|
460
540
|
expect(sort1.dir).to eq 'desc'
|
|
461
541
|
expect(sort2).to be_a Nodes::Sort
|
|
462
|
-
expect(sort2.name).to eq '
|
|
542
|
+
expect(sort2.name).to eq 'parent_name'
|
|
463
543
|
expect(sort2.dir).to eq 'asc'
|
|
464
544
|
end
|
|
465
545
|
|
|
466
|
-
it 'creates sorts based on
|
|
467
|
-
@s.sorts = ['id DESC', { name: '
|
|
546
|
+
it 'creates sorts based on attributes, alias and uppercase directions in array format' do
|
|
547
|
+
@s.sorts = ['id DESC', { name: 'daddy', dir: 'ASC' }]
|
|
468
548
|
expect(@s.sorts.size).to eq(2)
|
|
469
549
|
sort1, sort2 = @s.sorts
|
|
470
550
|
expect(sort1).to be_a Nodes::Sort
|
|
471
551
|
expect(sort1.name).to eq 'id'
|
|
472
552
|
expect(sort1.dir).to eq 'desc'
|
|
473
553
|
expect(sort2).to be_a Nodes::Sort
|
|
474
|
-
expect(sort2.name).to eq '
|
|
554
|
+
expect(sort2.name).to eq 'parent_name'
|
|
475
555
|
expect(sort2.dir).to eq 'asc'
|
|
476
556
|
end
|
|
477
557
|
|
|
478
|
-
it 'creates sorts based on
|
|
558
|
+
it 'creates sorts based on attributes, alias and different directions
|
|
479
559
|
in array format' do
|
|
480
|
-
@s.sorts = ['id DESC', { name: '
|
|
560
|
+
@s.sorts = ['id DESC', { name: 'daddy', dir: nil }]
|
|
481
561
|
expect(@s.sorts.size).to eq(2)
|
|
482
562
|
sort1, sort2 = @s.sorts
|
|
483
563
|
expect(sort1).to be_a Nodes::Sort
|
|
484
564
|
expect(sort1.name).to eq 'id'
|
|
485
565
|
expect(sort1.dir).to eq 'desc'
|
|
486
566
|
expect(sort2).to be_a Nodes::Sort
|
|
487
|
-
expect(sort2.name).to eq '
|
|
567
|
+
expect(sort2.name).to eq 'parent_name'
|
|
488
568
|
expect(sort2.dir).to eq 'asc'
|
|
489
569
|
end
|
|
490
570
|
|
|
491
|
-
it 'creates sorts based on
|
|
571
|
+
it 'creates sorts based on attributes, alias and directions in hash format' do
|
|
492
572
|
@s.sorts = {
|
|
493
573
|
'0' => { name: 'id', dir: 'desc' },
|
|
494
|
-
'1' => { name: '
|
|
574
|
+
'1' => { name: 'daddy', dir: 'asc' }
|
|
495
575
|
}
|
|
496
576
|
expect(@s.sorts.size).to eq(2)
|
|
497
577
|
expect(@s.sorts).to be_all { |s| Nodes::Sort === s }
|
|
498
578
|
id_sort = @s.sorts.detect { |s| s.name == 'id' }
|
|
499
|
-
|
|
579
|
+
daddy_sort = @s.sorts.detect { |s| s.name == 'parent_name' }
|
|
500
580
|
expect(id_sort.dir).to eq 'desc'
|
|
501
|
-
expect(
|
|
581
|
+
expect(daddy_sort.dir).to eq 'asc'
|
|
502
582
|
end
|
|
503
583
|
|
|
504
|
-
it 'creates sorts based on
|
|
584
|
+
it 'creates sorts based on attributes, alias and uppercase directions
|
|
505
585
|
in hash format' do
|
|
506
586
|
@s.sorts = {
|
|
507
587
|
'0' => { name: 'id', dir: 'DESC' },
|
|
508
|
-
'1' => { name: '
|
|
588
|
+
'1' => { name: 'daddy', dir: 'ASC' }
|
|
509
589
|
}
|
|
510
590
|
expect(@s.sorts.size).to eq(2)
|
|
511
591
|
expect(@s.sorts).to be_all { |s| Nodes::Sort === s }
|
|
512
592
|
id_sort = @s.sorts.detect { |s| s.name == 'id' }
|
|
513
|
-
|
|
593
|
+
daddy_sort = @s.sorts.detect { |s| s.name == 'parent_name' }
|
|
514
594
|
expect(id_sort.dir).to eq 'desc'
|
|
515
|
-
expect(
|
|
595
|
+
expect(daddy_sort.dir).to eq 'asc'
|
|
516
596
|
end
|
|
517
597
|
|
|
518
|
-
it 'creates sorts based on
|
|
598
|
+
it 'creates sorts based on attributes, alias and different directions
|
|
519
599
|
in hash format' do
|
|
520
600
|
@s.sorts = {
|
|
521
601
|
'0' => { name: 'id', dir: 'DESC' },
|
|
522
|
-
'1' => { name: '
|
|
602
|
+
'1' => { name: 'daddy', dir: nil }
|
|
523
603
|
}
|
|
524
604
|
expect(@s.sorts.size).to eq(2)
|
|
525
605
|
expect(@s.sorts).to be_all { |s| Nodes::Sort === s }
|
|
526
606
|
id_sort = @s.sorts.detect { |s| s.name == 'id' }
|
|
527
|
-
|
|
607
|
+
daddy_sort = @s.sorts.detect { |s| s.name == 'parent_name' }
|
|
528
608
|
expect(id_sort.dir).to eq 'desc'
|
|
529
|
-
expect(
|
|
609
|
+
expect(daddy_sort.dir).to eq 'asc'
|
|
530
610
|
end
|
|
531
611
|
|
|
532
612
|
it 'overrides existing sort' do
|
|
@@ -554,6 +634,39 @@ module Ransack
|
|
|
554
634
|
|
|
555
635
|
Ransack.options = default
|
|
556
636
|
end
|
|
637
|
+
|
|
638
|
+
it "PG's sort option with double name", if: ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" do
|
|
639
|
+
default = Ransack.options.clone
|
|
640
|
+
|
|
641
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
642
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC"
|
|
643
|
+
|
|
644
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_first }
|
|
645
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
646
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC NULLS FIRST"
|
|
647
|
+
s = Search.new(Person, s: 'doubled_name desc')
|
|
648
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" DESC NULLS LAST"
|
|
649
|
+
|
|
650
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_last }
|
|
651
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
652
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC NULLS LAST"
|
|
653
|
+
s = Search.new(Person, s: 'doubled_name desc')
|
|
654
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" DESC NULLS FIRST"
|
|
655
|
+
|
|
656
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_always_first }
|
|
657
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
658
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC NULLS FIRST"
|
|
659
|
+
s = Search.new(Person, s: 'doubled_name desc')
|
|
660
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" DESC NULLS FIRST"
|
|
661
|
+
|
|
662
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_always_last }
|
|
663
|
+
s = Search.new(Person, s: 'doubled_name asc')
|
|
664
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" ASC NULLS LAST"
|
|
665
|
+
s = Search.new(Person, s: 'doubled_name desc')
|
|
666
|
+
expect(s.result.to_sql).to eq "SELECT \"people\".* FROM \"people\" ORDER BY \"people\".\"name\" || \"people\".\"name\" DESC NULLS LAST"
|
|
667
|
+
|
|
668
|
+
Ransack.options = default
|
|
669
|
+
end
|
|
557
670
|
end
|
|
558
671
|
|
|
559
672
|
describe '#method_missing' do
|
data/spec/support/schema.rb
CHANGED
|
@@ -138,6 +138,45 @@ class Article < ActiveRecord::Base
|
|
|
138
138
|
alias_attribute :content, :body
|
|
139
139
|
|
|
140
140
|
default_scope { where("'default_scope' = 'default_scope'") }
|
|
141
|
+
scope :latest_comment_cont, lambda { |msg|
|
|
142
|
+
join = <<-SQL
|
|
143
|
+
(LEFT OUTER JOIN (
|
|
144
|
+
SELECT
|
|
145
|
+
comments.*,
|
|
146
|
+
row_number() OVER (PARTITION BY comments.article_id ORDER BY comments.id DESC) AS rownum
|
|
147
|
+
FROM comments
|
|
148
|
+
) AS latest_comment
|
|
149
|
+
ON latest_comment.article_id = article.id
|
|
150
|
+
AND latest_comment.rownum = 1
|
|
151
|
+
)
|
|
152
|
+
SQL
|
|
153
|
+
.squish
|
|
154
|
+
|
|
155
|
+
joins(join).where("latest_comment.body ILIKE ?", "%#{msg}%")
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
ransacker :title_type, formatter: lambda { |tuples|
|
|
159
|
+
title, type = JSON.parse(tuples)
|
|
160
|
+
Arel::Nodes::Grouping.new(
|
|
161
|
+
[
|
|
162
|
+
Arel::Nodes.build_quoted(title),
|
|
163
|
+
Arel::Nodes.build_quoted(type)
|
|
164
|
+
]
|
|
165
|
+
)
|
|
166
|
+
} do |_parent|
|
|
167
|
+
articles = Article.arel_table
|
|
168
|
+
Arel::Nodes::Grouping.new(
|
|
169
|
+
%i[title type].map do |field|
|
|
170
|
+
Arel::Nodes::NamedFunction.new(
|
|
171
|
+
'COALESCE',
|
|
172
|
+
[
|
|
173
|
+
Arel::Nodes::NamedFunction.new('TRIM', [articles[field]]),
|
|
174
|
+
Arel::Nodes.build_quoted('')
|
|
175
|
+
]
|
|
176
|
+
)
|
|
177
|
+
end
|
|
178
|
+
)
|
|
179
|
+
end
|
|
141
180
|
end
|
|
142
181
|
|
|
143
182
|
class StoryArticle < Article
|
|
@@ -176,6 +215,11 @@ class Note < ActiveRecord::Base
|
|
|
176
215
|
belongs_to :notable, polymorphic: true
|
|
177
216
|
end
|
|
178
217
|
|
|
218
|
+
class Account < ActiveRecord::Base
|
|
219
|
+
belongs_to :agent_account, class_name: "Account"
|
|
220
|
+
belongs_to :trade_account, class_name: "Account"
|
|
221
|
+
end
|
|
222
|
+
|
|
179
223
|
module Schema
|
|
180
224
|
def self.create
|
|
181
225
|
ActiveRecord::Migration.verbose = false
|
|
@@ -234,6 +278,11 @@ module Schema
|
|
|
234
278
|
t.integer :target_person_id
|
|
235
279
|
t.integer :article_id
|
|
236
280
|
end
|
|
281
|
+
|
|
282
|
+
create_table :accounts, force: true do |t|
|
|
283
|
+
t.belongs_to :agent_account
|
|
284
|
+
t.belongs_to :trade_account
|
|
285
|
+
end
|
|
237
286
|
end
|
|
238
287
|
|
|
239
288
|
10.times do
|
metadata
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ransack
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 3.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ernie Miller
|
|
8
8
|
- Ryan Bigg
|
|
9
9
|
- Jon Atack
|
|
10
10
|
- Sean Carroll
|
|
11
|
-
|
|
11
|
+
- David Rodríguez
|
|
12
|
+
autorequire:
|
|
12
13
|
bindir: bin
|
|
13
14
|
cert_chain: []
|
|
14
|
-
date:
|
|
15
|
+
date: 2022-05-09 00:00:00.000000000 Z
|
|
15
16
|
dependencies:
|
|
16
17
|
- !ruby/object:Gem::Dependency
|
|
17
18
|
name: activerecord
|
|
@@ -19,28 +20,28 @@ dependencies:
|
|
|
19
20
|
requirements:
|
|
20
21
|
- - ">="
|
|
21
22
|
- !ruby/object:Gem::Version
|
|
22
|
-
version:
|
|
23
|
+
version: 6.1.5
|
|
23
24
|
type: :runtime
|
|
24
25
|
prerelease: false
|
|
25
26
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
27
|
requirements:
|
|
27
28
|
- - ">="
|
|
28
29
|
- !ruby/object:Gem::Version
|
|
29
|
-
version:
|
|
30
|
+
version: 6.1.5
|
|
30
31
|
- !ruby/object:Gem::Dependency
|
|
31
32
|
name: activesupport
|
|
32
33
|
requirement: !ruby/object:Gem::Requirement
|
|
33
34
|
requirements:
|
|
34
35
|
- - ">="
|
|
35
36
|
- !ruby/object:Gem::Version
|
|
36
|
-
version:
|
|
37
|
+
version: 6.1.5
|
|
37
38
|
type: :runtime
|
|
38
39
|
prerelease: false
|
|
39
40
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
41
|
requirements:
|
|
41
42
|
- - ">="
|
|
42
43
|
- !ruby/object:Gem::Version
|
|
43
|
-
version:
|
|
44
|
+
version: 6.1.5
|
|
44
45
|
- !ruby/object:Gem::Dependency
|
|
45
46
|
name: i18n
|
|
46
47
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -69,9 +70,12 @@ files:
|
|
|
69
70
|
- ".github/FUNDING.yml"
|
|
70
71
|
- ".github/SECURITY.md"
|
|
71
72
|
- ".github/workflows/cronjob.yml"
|
|
73
|
+
- ".github/workflows/deploy.yml"
|
|
72
74
|
- ".github/workflows/rubocop.yml"
|
|
75
|
+
- ".github/workflows/test-deploy.yml"
|
|
73
76
|
- ".github/workflows/test.yml"
|
|
74
77
|
- ".gitignore"
|
|
78
|
+
- ".nojekyll"
|
|
75
79
|
- ".rubocop.yml"
|
|
76
80
|
- CHANGELOG.md
|
|
77
81
|
- CONTRIBUTING.md
|
|
@@ -81,20 +85,70 @@ files:
|
|
|
81
85
|
- Rakefile
|
|
82
86
|
- bug_report_templates/test-ransack-scope-and-column-same-name.rb
|
|
83
87
|
- bug_report_templates/test-ransacker-arel-present-predicate.rb
|
|
84
|
-
- docs
|
|
85
|
-
- docs
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
88
|
+
- docs/.gitignore
|
|
89
|
+
- docs/.nojekyll
|
|
90
|
+
- docs/babel.config.js
|
|
91
|
+
- docs/blog/2022-03-27-ransack-3.0.0.md
|
|
92
|
+
- docs/docs/getting-started/_category_.json
|
|
93
|
+
- docs/docs/getting-started/advanced-mode.md
|
|
94
|
+
- docs/docs/getting-started/configuration.md
|
|
95
|
+
- docs/docs/getting-started/search-matches.md
|
|
96
|
+
- docs/docs/getting-started/simple-mode.md
|
|
97
|
+
- docs/docs/getting-started/sorting.md
|
|
98
|
+
- docs/docs/getting-started/using-predicates.md
|
|
99
|
+
- docs/docs/going-further/_category_.json
|
|
100
|
+
- docs/docs/going-further/acts-as-taggable-on.md
|
|
101
|
+
- docs/docs/going-further/associations.md
|
|
102
|
+
- docs/docs/going-further/custom-predicates.md
|
|
103
|
+
- docs/docs/going-further/documentation.md
|
|
104
|
+
- docs/docs/going-further/exporting-to-csv.md
|
|
105
|
+
- docs/docs/going-further/external-guides.md
|
|
106
|
+
- docs/docs/going-further/form-customisation.md
|
|
107
|
+
- docs/docs/going-further/i18n.md
|
|
108
|
+
- docs/docs/going-further/img/create_release.png
|
|
109
|
+
- docs/docs/going-further/merging-searches.md
|
|
110
|
+
- docs/docs/going-further/other-notes.md
|
|
111
|
+
- docs/docs/going-further/polymorphic-search.md
|
|
112
|
+
- docs/docs/going-further/ransackers.md
|
|
113
|
+
- docs/docs/going-further/release_process.md
|
|
114
|
+
- docs/docs/going-further/saving-queries.md
|
|
115
|
+
- docs/docs/going-further/searching-postgres.md
|
|
116
|
+
- docs/docs/going-further/wiki-contributors.md
|
|
117
|
+
- docs/docs/intro.md
|
|
118
|
+
- docs/docusaurus.config.js
|
|
119
|
+
- docs/package.json
|
|
120
|
+
- docs/sidebars.js
|
|
121
|
+
- docs/src/components/HomepageFeatures/index.js
|
|
122
|
+
- docs/src/components/HomepageFeatures/styles.module.css
|
|
123
|
+
- docs/src/css/custom.css
|
|
124
|
+
- docs/src/pages/index.module.css
|
|
125
|
+
- docs/src/pages/markdown-page.md
|
|
126
|
+
- docs/static/.nojekyll
|
|
127
|
+
- docs/static/img/docusaurus.png
|
|
128
|
+
- docs/static/img/favicon.ico
|
|
129
|
+
- docs/static/img/logo.svg
|
|
130
|
+
- docs/static/img/tutorial/docsVersionDropdown.png
|
|
131
|
+
- docs/static/img/tutorial/localeDropdown.png
|
|
132
|
+
- docs/static/img/undraw_docusaurus_mountain.svg
|
|
133
|
+
- docs/static/img/undraw_docusaurus_react.svg
|
|
134
|
+
- docs/static/img/undraw_docusaurus_tree.svg
|
|
135
|
+
- docs/static/logo/ransack-h.png
|
|
136
|
+
- docs/static/logo/ransack-h.svg
|
|
137
|
+
- docs/static/logo/ransack-v.png
|
|
138
|
+
- docs/static/logo/ransack-v.svg
|
|
139
|
+
- docs/static/logo/ransack.png
|
|
140
|
+
- docs/static/logo/ransack.svg
|
|
141
|
+
- docs/yarn.lock
|
|
142
|
+
- lib/polyamorous.rb
|
|
92
143
|
- lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb
|
|
93
144
|
- lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb
|
|
94
145
|
- lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb
|
|
95
|
-
- lib/polyamorous/
|
|
96
|
-
- lib/polyamorous/
|
|
97
|
-
- lib/polyamorous/
|
|
146
|
+
- lib/polyamorous/activerecord_7.0_ruby_2/join_association.rb
|
|
147
|
+
- lib/polyamorous/activerecord_7.0_ruby_2/join_dependency.rb
|
|
148
|
+
- lib/polyamorous/activerecord_7.0_ruby_2/reflection.rb
|
|
149
|
+
- lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb
|
|
150
|
+
- lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb
|
|
151
|
+
- lib/polyamorous/activerecord_7.1_ruby_2/reflection.rb
|
|
98
152
|
- lib/polyamorous/join.rb
|
|
99
153
|
- lib/polyamorous/polyamorous.rb
|
|
100
154
|
- lib/polyamorous/swapping_reflection_class.rb
|
|
@@ -137,6 +191,7 @@ files:
|
|
|
137
191
|
- lib/ransack/locale/ro.yml
|
|
138
192
|
- lib/ransack/locale/ru.yml
|
|
139
193
|
- lib/ransack/locale/sk.yml
|
|
194
|
+
- lib/ransack/locale/sv.yml
|
|
140
195
|
- lib/ransack/locale/tr.yml
|
|
141
196
|
- lib/ransack/locale/zh-CN.yml
|
|
142
197
|
- lib/ransack/locale/zh-TW.yml
|
|
@@ -155,12 +210,6 @@ files:
|
|
|
155
210
|
- lib/ransack/translate.rb
|
|
156
211
|
- lib/ransack/version.rb
|
|
157
212
|
- lib/ransack/visitor.rb
|
|
158
|
-
- logo/ransack-h.png
|
|
159
|
-
- logo/ransack-h.svg
|
|
160
|
-
- logo/ransack-v.png
|
|
161
|
-
- logo/ransack-v.svg
|
|
162
|
-
- logo/ransack.png
|
|
163
|
-
- logo/ransack.svg
|
|
164
213
|
- ransack.gemspec
|
|
165
214
|
- spec/blueprints/articles.rb
|
|
166
215
|
- spec/blueprints/comments.rb
|
|
@@ -170,6 +219,7 @@ files:
|
|
|
170
219
|
- spec/console.rb
|
|
171
220
|
- spec/helpers/polyamorous_helper.rb
|
|
172
221
|
- spec/helpers/ransack_helper.rb
|
|
222
|
+
- spec/polyamorous/activerecord_compatibility_spec.rb
|
|
173
223
|
- spec/polyamorous/join_association_spec.rb
|
|
174
224
|
- spec/polyamorous/join_dependency_spec.rb
|
|
175
225
|
- spec/polyamorous/join_spec.rb
|
|
@@ -190,7 +240,7 @@ homepage: https://github.com/activerecord-hackery/ransack
|
|
|
190
240
|
licenses:
|
|
191
241
|
- MIT
|
|
192
242
|
metadata: {}
|
|
193
|
-
post_install_message:
|
|
243
|
+
post_install_message:
|
|
194
244
|
rdoc_options: []
|
|
195
245
|
require_paths:
|
|
196
246
|
- lib
|
|
@@ -198,17 +248,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
198
248
|
requirements:
|
|
199
249
|
- - ">="
|
|
200
250
|
- !ruby/object:Gem::Version
|
|
201
|
-
version: '2.
|
|
251
|
+
version: '2.7'
|
|
202
252
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
203
253
|
requirements:
|
|
204
254
|
- - ">="
|
|
205
255
|
- !ruby/object:Gem::Version
|
|
206
256
|
version: '0'
|
|
207
257
|
requirements: []
|
|
208
|
-
rubygems_version: 3.0.
|
|
209
|
-
signing_key:
|
|
258
|
+
rubygems_version: 3.4.0.dev
|
|
259
|
+
signing_key:
|
|
210
260
|
specification_version: 4
|
|
211
|
-
summary: Object-based searching for Active Record
|
|
261
|
+
summary: Object-based searching for Active Record.
|
|
212
262
|
test_files:
|
|
213
263
|
- spec/blueprints/articles.rb
|
|
214
264
|
- spec/blueprints/comments.rb
|
|
@@ -218,6 +268,7 @@ test_files:
|
|
|
218
268
|
- spec/console.rb
|
|
219
269
|
- spec/helpers/polyamorous_helper.rb
|
|
220
270
|
- spec/helpers/ransack_helper.rb
|
|
271
|
+
- spec/polyamorous/activerecord_compatibility_spec.rb
|
|
221
272
|
- spec/polyamorous/join_association_spec.rb
|
|
222
273
|
- spec/polyamorous/join_dependency_spec.rb
|
|
223
274
|
- spec/polyamorous/join_spec.rb
|
data/docs/release_process.md
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
## Release Process
|
|
2
|
-
|
|
3
|
-
*For maintainers of Ransack.*
|
|
4
|
-
|
|
5
|
-
To release a new version of Ransack and publish it to RubyGems, take the following steps:
|
|
6
|
-
|
|
7
|
-
- Create a new release, marked `Prerelease`.
|
|
8
|
-
<<<<<<< Updated upstream
|
|
9
|
-
- Update the versions file to the new release, commit and push to `master`.
|
|
10
|
-
=======
|
|
11
|
-
- Update the [version.rb](../lib/ransack/version.rb) file to the new release, commit and push to `master`.
|
|
12
|
-
>>>>>>> Stashed changes
|
|
13
|
-
- From the terminal, run the following commands
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
rake build
|
|
17
|
-
rake release
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-

|
|
@@ -1,24 +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
|
-
|
|
20
|
-
def ==(other)
|
|
21
|
-
base_klass == other.base_klass
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|