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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/cronjob.yml +6 -9
  3. data/.github/workflows/deploy.yml +35 -0
  4. data/.github/workflows/rubocop.yml +1 -1
  5. data/.github/workflows/test-deploy.yml +29 -0
  6. data/.github/workflows/test.yml +16 -40
  7. data/.nojekyll +0 -0
  8. data/CHANGELOG.md +137 -11
  9. data/CONTRIBUTING.md +4 -3
  10. data/Gemfile +2 -2
  11. data/README.md +45 -973
  12. data/docs/.gitignore +19 -0
  13. data/docs/.nojekyll +0 -0
  14. data/docs/babel.config.js +3 -0
  15. data/docs/blog/2022-03-27-ransack-3.0.0.md +20 -0
  16. data/docs/docs/getting-started/_category_.json +4 -0
  17. data/docs/docs/getting-started/advanced-mode.md +46 -0
  18. data/docs/docs/getting-started/configuration.md +47 -0
  19. data/docs/docs/getting-started/search-matches.md +67 -0
  20. data/docs/docs/getting-started/simple-mode.md +284 -0
  21. data/docs/docs/getting-started/sorting.md +79 -0
  22. data/docs/docs/getting-started/using-predicates.md +282 -0
  23. data/docs/docs/going-further/_category_.json +4 -0
  24. data/docs/docs/going-further/acts-as-taggable-on.md +114 -0
  25. data/docs/docs/going-further/associations.md +70 -0
  26. data/docs/docs/going-further/custom-predicates.md +52 -0
  27. data/docs/docs/going-further/documentation.md +43 -0
  28. data/docs/docs/going-further/exporting-to-csv.md +49 -0
  29. data/docs/docs/going-further/external-guides.md +57 -0
  30. data/docs/docs/going-further/form-customisation.md +63 -0
  31. data/docs/docs/going-further/i18n.md +53 -0
  32. data/docs/docs/going-further/merging-searches.md +41 -0
  33. data/docs/docs/going-further/other-notes.md +428 -0
  34. data/docs/docs/going-further/polymorphic-search.md +40 -0
  35. data/docs/docs/going-further/ransackers.md +331 -0
  36. data/docs/docs/going-further/release_process.md +36 -0
  37. data/docs/docs/going-further/saving-queries.md +82 -0
  38. data/docs/docs/going-further/searching-postgres.md +57 -0
  39. data/docs/docs/going-further/wiki-contributors.md +82 -0
  40. data/docs/docs/intro.md +99 -0
  41. data/docs/docusaurus.config.js +107 -0
  42. data/docs/package.json +37 -0
  43. data/docs/sidebars.js +31 -0
  44. data/docs/src/components/HomepageFeatures/index.js +64 -0
  45. data/docs/src/components/HomepageFeatures/styles.module.css +11 -0
  46. data/docs/src/css/custom.css +39 -0
  47. data/docs/src/pages/index.module.css +23 -0
  48. data/docs/src/pages/markdown-page.md +7 -0
  49. data/docs/static/.nojekyll +0 -0
  50. data/docs/static/img/docusaurus.png +0 -0
  51. data/docs/static/img/favicon.ico +0 -0
  52. data/docs/static/img/logo.svg +1 -0
  53. data/docs/static/img/tutorial/docsVersionDropdown.png +0 -0
  54. data/docs/static/img/tutorial/localeDropdown.png +0 -0
  55. data/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
  56. data/docs/static/img/undraw_docusaurus_react.svg +170 -0
  57. data/docs/static/img/undraw_docusaurus_tree.svg +40 -0
  58. data/docs/yarn.lock +7671 -0
  59. data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +0 -4
  60. data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +0 -1
  61. data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -1
  62. data/lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb +1 -0
  63. data/lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb +1 -0
  64. data/lib/polyamorous/activerecord_7.1_ruby_2/reflection.rb +1 -0
  65. data/lib/polyamorous.rb +1 -0
  66. data/lib/ransack/adapters/active_record/base.rb +1 -3
  67. data/lib/ransack/adapters/active_record/context.rb +24 -51
  68. data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +2 -9
  69. data/lib/ransack/configuration.rb +16 -2
  70. data/lib/ransack/constants.rb +0 -3
  71. data/lib/ransack/helpers/form_helper.rb +11 -3
  72. data/lib/ransack/locale/sv.yml +70 -0
  73. data/lib/ransack/nodes/sort.rb +2 -2
  74. data/lib/ransack/search.rb +4 -3
  75. data/lib/ransack/translate.rb +1 -1
  76. data/lib/ransack/version.rb +1 -1
  77. data/ransack.gemspec +5 -5
  78. data/spec/helpers/polyamorous_helper.rb +2 -8
  79. data/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
  80. data/spec/polyamorous/join_association_spec.rb +1 -6
  81. data/spec/polyamorous/join_dependency_spec.rb +0 -16
  82. data/spec/ransack/adapters/active_record/base_spec.rb +28 -11
  83. data/spec/ransack/configuration_spec.rb +14 -0
  84. data/spec/ransack/helpers/form_helper_spec.rb +57 -2
  85. data/spec/ransack/nodes/condition_spec.rb +13 -0
  86. data/spec/ransack/search_spec.rb +140 -27
  87. data/spec/support/schema.rb +49 -0
  88. metadata +80 -29
  89. data/docs/release_process.md +0 -20
  90. data/lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb +0 -24
  91. data/lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +0 -79
  92. data/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +0 -11
  93. data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +0 -1
  94. data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +0 -80
  95. data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +0 -1
  96. /data/docs/{img → docs/going-further/img}/create_release.png +0 -0
  97. /data/{logo → docs/static/logo}/ransack-h.png +0 -0
  98. /data/{logo → docs/static/logo}/ransack-h.svg +0 -0
  99. /data/{logo → docs/static/logo}/ransack-v.png +0 -0
  100. /data/{logo → docs/static/logo}/ransack-v.svg +0 -0
  101. /data/{logo → docs/static/logo}/ransack.png +0 -0
  102. /data/{logo → docs/static/logo}/ransack.svg +0 -0
  103. /data/lib/polyamorous/{activerecord_6.2_ruby_2 → activerecord_7.0_ruby_2}/join_association.rb +0 -0
  104. /data/lib/polyamorous/{activerecord_6.2_ruby_2 → activerecord_7.0_ruby_2}/join_dependency.rb +0 -0
  105. /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 {
@@ -20,10 +20,42 @@ module Ransack
20
20
  Search.new(Person, name_eq: 'foobar')
21
21
  end
22
22
 
23
- it 'strip leading & trailing whitespace before building' do
24
- expect_any_instance_of(Search).to receive(:build)
25
- .with({ 'name_eq' => 'foobar' })
26
- Search.new(Person, name_eq: ' foobar ')
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 multiple attributes/directions in array format' do
455
- @s.sorts = ['id desc', { name: 'name', dir: 'asc' }]
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 'name'
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 multiple attributes and uppercase directions in array format' do
467
- @s.sorts = ['id DESC', { name: 'name', dir: 'ASC' }]
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 'name'
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 multiple attributes and different directions
558
+ it 'creates sorts based on attributes, alias and different directions
479
559
  in array format' do
480
- @s.sorts = ['id DESC', { name: 'name', dir: nil }]
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 'name'
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 multiple attributes/directions in hash format' do
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: 'name', dir: 'asc' }
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
- name_sort = @s.sorts.detect { |s| s.name == 'name' }
579
+ daddy_sort = @s.sorts.detect { |s| s.name == 'parent_name' }
500
580
  expect(id_sort.dir).to eq 'desc'
501
- expect(name_sort.dir).to eq 'asc'
581
+ expect(daddy_sort.dir).to eq 'asc'
502
582
  end
503
583
 
504
- it 'creates sorts based on multiple attributes and uppercase directions
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: 'name', dir: 'ASC' }
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
- name_sort = @s.sorts.detect { |s| s.name == 'name' }
593
+ daddy_sort = @s.sorts.detect { |s| s.name == 'parent_name' }
514
594
  expect(id_sort.dir).to eq 'desc'
515
- expect(name_sort.dir).to eq 'asc'
595
+ expect(daddy_sort.dir).to eq 'asc'
516
596
  end
517
597
 
518
- it 'creates sorts based on multiple attributes and different directions
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: 'name', dir: nil }
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
- name_sort = @s.sorts.detect { |s| s.name == 'name' }
607
+ daddy_sort = @s.sorts.detect { |s| s.name == 'parent_name' }
528
608
  expect(id_sort.dir).to eq 'desc'
529
- expect(name_sort.dir).to eq 'asc'
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
@@ -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.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
- autorequire:
11
+ - David Rodríguez
12
+ autorequire:
12
13
  bindir: bin
13
14
  cert_chain: []
14
- date: 2021-01-23 00:00:00.000000000 Z
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: 5.2.4
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: 5.2.4
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: 5.2.4
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: 5.2.4
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/img/create_release.png
85
- - docs/release_process.md
86
- - lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb
87
- - lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb
88
- - lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb
89
- - lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb
90
- - lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb
91
- - lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb
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/activerecord_6.2_ruby_2/join_association.rb
96
- - lib/polyamorous/activerecord_6.2_ruby_2/join_dependency.rb
97
- - lib/polyamorous/activerecord_6.2_ruby_2/reflection.rb
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.6'
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.3
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 and Mongoid (currently).
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
@@ -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
- ![Create a Release](img/create_release.png)
@@ -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