ransack 2.4.2 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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