ransack 1.8.4 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +3 -0
- data/.github/SECURITY.md +12 -0
- data/.github/workflows/cronjob.yml +102 -0
- data/.github/workflows/deploy.yml +35 -0
- data/.github/workflows/rubocop.yml +20 -0
- data/.github/workflows/test-deploy.yml +29 -0
- data/.github/workflows/test.yml +130 -0
- data/.gitignore +3 -0
- data/{lib/ransack/adapters/mongoid/3.2/.gitkeep → .nojekyll} +0 -0
- data/.rubocop.yml +44 -0
- data/CHANGELOG.md +352 -0
- data/CONTRIBUTING.md +25 -13
- data/Gemfile +26 -27
- data/README.md +65 -815
- data/Rakefile +1 -22
- data/bug_report_templates/test-ransack-scope-and-column-same-name.rb +78 -0
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +71 -0
- data/docs/.gitignore +19 -0
- data/docs/.nojekyll +0 -0
- data/docs/babel.config.js +3 -0
- data/docs/blog/2022-03-27-ransack-3.0.0.md +20 -0
- data/docs/docs/getting-started/_category_.json +4 -0
- data/docs/docs/getting-started/advanced-mode.md +46 -0
- data/docs/docs/getting-started/configuration.md +47 -0
- data/docs/docs/getting-started/search-matches.md +67 -0
- data/docs/docs/getting-started/simple-mode.md +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/img/create_release.png +0 -0
- data/docs/docs/going-further/merging-searches.md +41 -0
- data/docs/docs/going-further/other-notes.md +428 -0
- data/docs/docs/going-further/polymorphic-search.md +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 +120 -0
- data/docs/package.json +38 -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/static/logo/ransack-h.png +0 -0
- data/docs/static/logo/ransack-h.svg +34 -0
- data/docs/static/logo/ransack-v.png +0 -0
- data/docs/static/logo/ransack-v.svg +34 -0
- data/docs/static/logo/ransack.png +0 -0
- data/docs/static/logo/ransack.svg +21 -0
- data/docs/yarn.lock +8436 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +70 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +92 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/join.rb +70 -0
- data/lib/polyamorous/polyamorous.rb +24 -0
- data/lib/polyamorous/swapping_reflection_class.rb +11 -0
- data/lib/polyamorous/tree_node.rb +7 -0
- data/lib/polyamorous.rb +1 -0
- data/lib/ransack/adapters/active_record/base.rb +14 -3
- data/lib/ransack/adapters/active_record/context.rb +140 -196
- data/lib/ransack/adapters/active_record/ransack/constants.rb +19 -4
- data/lib/ransack/adapters/active_record/ransack/context.rb +9 -19
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +7 -7
- data/lib/ransack/adapters/active_record/ransack/translate.rb +1 -5
- data/lib/ransack/adapters/active_record/ransack/visitor.rb +23 -0
- data/lib/ransack/adapters/active_record.rb +0 -9
- data/lib/ransack/adapters.rb +2 -0
- data/lib/ransack/configuration.rb +52 -2
- data/lib/ransack/constants.rb +1 -5
- data/lib/ransack/context.rb +29 -24
- data/lib/ransack/helpers/form_builder.rb +12 -6
- data/lib/ransack/helpers/form_helper.rb +11 -3
- data/lib/ransack/helpers.rb +1 -1
- data/lib/ransack/locale/ar.yml +70 -0
- data/lib/ransack/locale/az.yml +70 -0
- data/lib/ransack/locale/bg.yml +70 -0
- data/lib/ransack/locale/ca.yml +70 -0
- data/lib/ransack/locale/el.yml +70 -0
- data/lib/ransack/locale/es.yml +22 -22
- data/lib/ransack/locale/fa.yml +70 -0
- data/lib/ransack/locale/fi.yml +71 -0
- data/lib/ransack/locale/nl.yml +4 -4
- data/lib/ransack/locale/ru.yml +70 -0
- data/lib/ransack/locale/sk.yml +70 -0
- data/lib/ransack/locale/sv.yml +70 -0
- data/lib/ransack/locale/tr.yml +70 -0
- data/lib/ransack/locale/zh-CN.yml +12 -12
- data/lib/ransack/nodes/attribute.rb +2 -2
- data/lib/ransack/nodes/condition.rb +7 -1
- data/lib/ransack/nodes/grouping.rb +3 -8
- data/lib/ransack/nodes/sort.rb +3 -3
- data/lib/ransack/nodes/value.rb +3 -3
- data/lib/ransack/predicate.rb +13 -20
- data/lib/ransack/search.rb +7 -4
- data/lib/ransack/translate.rb +115 -115
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +1 -12
- data/lib/ransack.rb +7 -5
- data/ransack.gemspec +9 -25
- data/spec/blueprints/articles.rb +1 -1
- data/spec/blueprints/comments.rb +1 -1
- data/spec/blueprints/notes.rb +1 -1
- data/spec/blueprints/tags.rb +1 -1
- data/spec/console.rb +5 -5
- data/spec/helpers/polyamorous_helper.rb +13 -0
- data/spec/helpers/ransack_helper.rb +1 -1
- data/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
- data/spec/polyamorous/join_association_spec.rb +30 -0
- data/spec/polyamorous/join_dependency_spec.rb +81 -0
- data/spec/polyamorous/join_spec.rb +19 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +105 -11
- data/spec/ransack/adapters/active_record/context_spec.rb +63 -24
- data/spec/ransack/configuration_spec.rb +24 -0
- data/spec/ransack/helpers/form_builder_spec.rb +3 -15
- data/spec/ransack/helpers/form_helper_spec.rb +135 -168
- data/spec/ransack/nodes/condition_spec.rb +13 -0
- data/spec/ransack/nodes/grouping_spec.rb +2 -2
- data/spec/ransack/nodes/value_spec.rb +115 -0
- data/spec/ransack/predicate_spec.rb +54 -2
- data/spec/ransack/search_spec.rb +266 -36
- data/spec/spec_helper.rb +14 -5
- data/spec/support/schema.rb +99 -21
- metadata +117 -187
- data/.travis.yml +0 -86
- data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
- data/lib/ransack/adapters/active_record/3.0/context.rb +0 -203
- data/lib/ransack/adapters/active_record/3.1/context.rb +0 -212
- data/lib/ransack/adapters/active_record/3.2/context.rb +0 -44
- data/lib/ransack/adapters/active_record/compat.rb +0 -14
- data/lib/ransack/adapters/mongoid/attributes/attribute.rb +0 -37
- data/lib/ransack/adapters/mongoid/attributes/order_predications.rb +0 -17
- data/lib/ransack/adapters/mongoid/attributes/predications.rb +0 -141
- data/lib/ransack/adapters/mongoid/base.rb +0 -134
- data/lib/ransack/adapters/mongoid/context.rb +0 -212
- data/lib/ransack/adapters/mongoid/inquiry_hash.rb +0 -23
- data/lib/ransack/adapters/mongoid/ransack/constants.rb +0 -88
- data/lib/ransack/adapters/mongoid/ransack/context.rb +0 -60
- data/lib/ransack/adapters/mongoid/ransack/nodes/condition.rb +0 -27
- data/lib/ransack/adapters/mongoid/ransack/translate.rb +0 -13
- data/lib/ransack/adapters/mongoid/ransack/visitor.rb +0 -24
- data/lib/ransack/adapters/mongoid/table.rb +0 -35
- data/lib/ransack/adapters/mongoid.rb +0 -15
- data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -314
- data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
- data/spec/mongoid/configuration_spec.rb +0 -162
- data/spec/mongoid/dependencies_spec.rb +0 -8
- data/spec/mongoid/helpers/ransack_helper.rb +0 -11
- data/spec/mongoid/nodes/condition_spec.rb +0 -49
- data/spec/mongoid/nodes/grouping_spec.rb +0 -13
- data/spec/mongoid/predicate_spec.rb +0 -155
- data/spec/mongoid/search_spec.rb +0 -445
- data/spec/mongoid/support/mongoid.yml +0 -11
- data/spec/mongoid/support/schema.rb +0 -135
- data/spec/mongoid/translate_spec.rb +0 -14
- data/spec/mongoid_spec_helper.rb +0 -63
- data/spec/ransack/dependencies_spec.rb +0 -12
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Polyamorous
|
|
4
|
+
describe JoinDependency do
|
|
5
|
+
|
|
6
|
+
context 'with symbol joins' do
|
|
7
|
+
subject { new_join_dependency Person, articles: :comments }
|
|
8
|
+
|
|
9
|
+
specify { expect(subject.send(:join_root).drop(1).size)
|
|
10
|
+
.to eq(2) }
|
|
11
|
+
specify { expect(subject.send(:join_root).drop(1).map(&:join_type).uniq)
|
|
12
|
+
.to eq [Polyamorous::InnerJoin] }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
context 'with has_many :through association' do
|
|
16
|
+
subject { new_join_dependency Person, :authored_article_comments }
|
|
17
|
+
|
|
18
|
+
specify { expect(subject.send(:join_root).drop(1).size)
|
|
19
|
+
.to eq 1 }
|
|
20
|
+
specify { expect(subject.send(:join_root).drop(1).first.table_name)
|
|
21
|
+
.to eq 'comments' }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'with outer join' do
|
|
25
|
+
subject { new_join_dependency Person, new_join(:articles, :outer) }
|
|
26
|
+
|
|
27
|
+
specify { expect(subject.send(:join_root).drop(1).size)
|
|
28
|
+
.to eq 1 }
|
|
29
|
+
specify { expect(subject.send(:join_root).drop(1).first.join_type)
|
|
30
|
+
.to eq Polyamorous::OuterJoin }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context 'with nested outer joins' do
|
|
34
|
+
subject { new_join_dependency Person,
|
|
35
|
+
new_join(:articles, :outer) => new_join(:comments, :outer) }
|
|
36
|
+
|
|
37
|
+
specify { expect(subject.send(:join_root).drop(1).size)
|
|
38
|
+
.to eq 2 }
|
|
39
|
+
specify { expect(subject.send(:join_root).drop(1).map(&:join_type))
|
|
40
|
+
.to eq [Polyamorous::OuterJoin, Polyamorous::OuterJoin] }
|
|
41
|
+
specify { expect(subject.send(:join_root).drop(1).map(&:join_type).uniq)
|
|
42
|
+
.to eq [Polyamorous::OuterJoin] }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context 'with polymorphic belongs_to join' do
|
|
46
|
+
subject { new_join_dependency Note, new_join(:notable, :inner, Person) }
|
|
47
|
+
|
|
48
|
+
specify { expect(subject.send(:join_root).drop(1).size)
|
|
49
|
+
.to eq 1 }
|
|
50
|
+
specify { expect(subject.send(:join_root).drop(1).first.join_type)
|
|
51
|
+
.to eq Polyamorous::InnerJoin }
|
|
52
|
+
specify { expect(subject.send(:join_root).drop(1).first.table_name)
|
|
53
|
+
.to eq 'people' }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context 'with polymorphic belongs_to join and nested symbol join' do
|
|
57
|
+
subject { new_join_dependency Note,
|
|
58
|
+
new_join(:notable, :inner, Person) => :comments }
|
|
59
|
+
|
|
60
|
+
specify { expect(subject.send(:join_root).drop(1).size)
|
|
61
|
+
.to eq 2 }
|
|
62
|
+
specify { expect(subject.send(:join_root).drop(1).map(&:join_type).uniq)
|
|
63
|
+
.to eq [Polyamorous::InnerJoin] }
|
|
64
|
+
specify { expect(subject.send(:join_root).drop(1).first.table_name)
|
|
65
|
+
.to eq 'people' }
|
|
66
|
+
specify { expect(subject.send(:join_root).drop(1)[1].table_name)
|
|
67
|
+
.to eq 'comments' }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'with polymorphic belongs_to join and nested join' do
|
|
71
|
+
subject { new_join_dependency Note,
|
|
72
|
+
new_join(:notable, :outer, Person) => :comments }
|
|
73
|
+
specify { expect(subject.send(:join_root).drop(1).size).to eq 2 }
|
|
74
|
+
specify { expect(subject.send(:join_root).drop(1).map(&:join_type)).to eq [Polyamorous::OuterJoin, Polyamorous::InnerJoin] }
|
|
75
|
+
specify { expect(subject.send(:join_root).drop(1).first.table_name)
|
|
76
|
+
.to eq 'people' }
|
|
77
|
+
specify { expect(subject.send(:join_root).drop(1)[1].table_name)
|
|
78
|
+
.to eq 'comments' }
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Polyamorous
|
|
4
|
+
describe Join do
|
|
5
|
+
it 'is a tree node' do
|
|
6
|
+
join = new_join(:articles, :outer)
|
|
7
|
+
expect(join).to be_kind_of(TreeNode)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'can be added to a tree' do
|
|
11
|
+
join = new_join(:articles, :outer)
|
|
12
|
+
|
|
13
|
+
tree_hash = {}
|
|
14
|
+
join.add_to_tree(tree_hash)
|
|
15
|
+
|
|
16
|
+
expect(tree_hash[join]).to be {}
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -8,7 +8,6 @@ module Ransack
|
|
|
8
8
|
subject { ::ActiveRecord::Base }
|
|
9
9
|
|
|
10
10
|
it { should respond_to :ransack }
|
|
11
|
-
it { should respond_to :search }
|
|
12
11
|
|
|
13
12
|
describe '#search' do
|
|
14
13
|
subject { Person.ransack }
|
|
@@ -18,6 +17,13 @@ module Ransack
|
|
|
18
17
|
expect(subject.object).to be_an ::ActiveRecord::Relation
|
|
19
18
|
end
|
|
20
19
|
|
|
20
|
+
context "multiple database connection" do
|
|
21
|
+
it "does not raise error" do
|
|
22
|
+
expect { Person.ransack(name_cont: "test") }.not_to raise_error
|
|
23
|
+
expect { SubDB::OperationHistory.ransack(people_id_eq: 1) }.not_to raise_error
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
21
27
|
context 'with scopes' do
|
|
22
28
|
before do
|
|
23
29
|
allow(Person)
|
|
@@ -37,12 +43,12 @@ module Ransack
|
|
|
37
43
|
|
|
38
44
|
it 'applies stringy boolean scopes with true value in an array' do
|
|
39
45
|
s = Person.ransack('of_age' => ['true'])
|
|
40
|
-
expect(s.result.to_sql).to (include 'age >= 18')
|
|
46
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{(age >= '18')} : 'age >= 18')
|
|
41
47
|
end
|
|
42
48
|
|
|
43
49
|
it 'applies stringy boolean scopes with false value in an array' do
|
|
44
50
|
s = Person.ransack('of_age' => ['false'])
|
|
45
|
-
expect(s.result.to_sql).to (include 'age < 18')
|
|
51
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age < '18'} : 'age < 18')
|
|
46
52
|
end
|
|
47
53
|
|
|
48
54
|
it 'ignores unlisted scopes' do
|
|
@@ -62,15 +68,25 @@ module Ransack
|
|
|
62
68
|
|
|
63
69
|
it 'passes values to scopes' do
|
|
64
70
|
s = Person.ransack('over_age' => 18)
|
|
65
|
-
expect(s.result.to_sql).to (include 'age > 18')
|
|
71
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '18'} : 'age > 18')
|
|
66
72
|
end
|
|
67
73
|
|
|
68
74
|
it 'chains scopes' do
|
|
69
75
|
s = Person.ransack('over_age' => 18, 'active' => true)
|
|
70
|
-
expect(s.result.to_sql).to (include 'age > 18')
|
|
76
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '18'} : 'age > 18')
|
|
71
77
|
expect(s.result.to_sql).to (include 'active = 1')
|
|
72
78
|
end
|
|
73
79
|
|
|
80
|
+
it 'applies scopes that define string SQL joins' do
|
|
81
|
+
allow(Article)
|
|
82
|
+
.to receive(:ransackable_scopes)
|
|
83
|
+
.and_return([:latest_comment_cont])
|
|
84
|
+
|
|
85
|
+
# Including a negative condition to test removing the scope
|
|
86
|
+
s = Search.new(Article, notes_note_not_eq: 'Test', latest_comment_cont: 'Test')
|
|
87
|
+
expect(s.result.to_sql).to include 'latest_comment'
|
|
88
|
+
end
|
|
89
|
+
|
|
74
90
|
context "with sanitize_custom_scope_booleans set to false" do
|
|
75
91
|
before(:all) do
|
|
76
92
|
Ransack.configure { |c| c.sanitize_custom_scope_booleans = false }
|
|
@@ -82,20 +98,43 @@ module Ransack
|
|
|
82
98
|
|
|
83
99
|
it 'passes true values to scopes' do
|
|
84
100
|
s = Person.ransack('over_age' => 1)
|
|
85
|
-
expect(s.result.to_sql).to (include 'age > 1')
|
|
101
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '1'} : 'age > 1')
|
|
86
102
|
end
|
|
87
103
|
|
|
88
104
|
it 'passes false values to scopes' do
|
|
89
105
|
s = Person.ransack('over_age' => 0)
|
|
90
|
-
expect(s.result.to_sql).to (include 'age > 0')
|
|
106
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '0'} : 'age > 0')
|
|
91
107
|
end
|
|
92
108
|
end
|
|
109
|
+
|
|
110
|
+
context "with ransackable_scopes_skip_sanitize_args enabled for scope" do
|
|
111
|
+
before do
|
|
112
|
+
allow(Person)
|
|
113
|
+
.to receive(:ransackable_scopes_skip_sanitize_args)
|
|
114
|
+
.and_return([:over_age])
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'passes true values to scopes' do
|
|
118
|
+
s = Person.ransack('over_age' => 1)
|
|
119
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '1'} : 'age > 1')
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'passes false values to scopes' do
|
|
123
|
+
s = Person.ransack('over_age' => 0)
|
|
124
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '0'} : 'age > 0')
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
93
128
|
end
|
|
94
129
|
|
|
95
130
|
it 'does not raise exception for string :params argument' do
|
|
96
131
|
expect { Person.ransack('') }.to_not raise_error
|
|
97
132
|
end
|
|
98
133
|
|
|
134
|
+
it 'raises exception if ransack! called with unknown condition' do
|
|
135
|
+
expect { Person.ransack!(unknown_attr_eq: 'Ernie') }.to raise_error(ArgumentError)
|
|
136
|
+
end
|
|
137
|
+
|
|
99
138
|
it 'does not modify the parameters' do
|
|
100
139
|
params = { name_eq: '' }
|
|
101
140
|
expect { Person.ransack(params) }.not_to change { params }
|
|
@@ -117,14 +156,12 @@ module Ransack
|
|
|
117
156
|
it 'removes redundant joins from top query' do
|
|
118
157
|
s = Article.ransack(tags_name_not_eq: "Fantasy")
|
|
119
158
|
sql = s.result.to_sql
|
|
120
|
-
|
|
121
159
|
expect(sql).to_not include('LEFT OUTER JOIN')
|
|
122
160
|
end
|
|
123
161
|
|
|
124
162
|
it 'handles != for single values' do
|
|
125
163
|
s = Article.ransack(tags_name_not_eq: "Fantasy")
|
|
126
164
|
articles = s.result.to_a
|
|
127
|
-
|
|
128
165
|
expect(articles).to include marco
|
|
129
166
|
expect(articles).to_not include arthur
|
|
130
167
|
end
|
|
@@ -241,10 +278,12 @@ module Ransack
|
|
|
241
278
|
# end
|
|
242
279
|
|
|
243
280
|
it 'creates ransack attributes' do
|
|
281
|
+
person = Person.create!(name: 'Aric Smith')
|
|
282
|
+
|
|
244
283
|
s = Person.ransack(reversed_name_eq: 'htimS cirA')
|
|
245
284
|
expect(s.result.size).to eq(1)
|
|
246
285
|
|
|
247
|
-
expect(s.result.first).to eq
|
|
286
|
+
expect(s.result.first).to eq person
|
|
248
287
|
end
|
|
249
288
|
|
|
250
289
|
it 'can be accessed through associations' do
|
|
@@ -284,7 +323,11 @@ module Ransack
|
|
|
284
323
|
end
|
|
285
324
|
|
|
286
325
|
it 'should function correctly with a multi-parameter attribute' do
|
|
287
|
-
::ActiveRecord::
|
|
326
|
+
if ::ActiveRecord::VERSION::MAJOR >= 7
|
|
327
|
+
::ActiveRecord.default_timezone = :utc
|
|
328
|
+
else
|
|
329
|
+
::ActiveRecord::Base.default_timezone = :utc
|
|
330
|
+
end
|
|
288
331
|
Time.zone = 'UTC'
|
|
289
332
|
|
|
290
333
|
date = Date.current
|
|
@@ -429,6 +472,16 @@ module Ransack
|
|
|
429
472
|
end
|
|
430
473
|
end
|
|
431
474
|
|
|
475
|
+
it 'sorts with different join variants' do
|
|
476
|
+
comments = [
|
|
477
|
+
Comment.create(article: Article.create(title: 'Avenger'), person: Person.create(salary: 100_000)),
|
|
478
|
+
Comment.create(article: Article.create(title: 'Avenge'), person: Person.create(salary: 50_000)),
|
|
479
|
+
]
|
|
480
|
+
expect(Comment.ransack(article_title_cont: 'aven', s: 'person_salary desc').result).to eq(comments)
|
|
481
|
+
expect(Comment.joins(:person).ransack(s: 'persons_salarydesc', article_title_cont: 'aven').result).to eq(comments)
|
|
482
|
+
expect(Comment.joins(:person).ransack(article_title_cont: 'aven', s: 'persons_salary desc').result).to eq(comments)
|
|
483
|
+
end
|
|
484
|
+
|
|
432
485
|
it 'allows sort by `only_sort` field' do
|
|
433
486
|
s = Person.ransack(
|
|
434
487
|
's' => { '0' => { 'dir' => 'asc', 'name' => 'only_sort' } }
|
|
@@ -544,6 +597,37 @@ module Ransack
|
|
|
544
597
|
/BETWEEN 2 AND 6 GROUP BY articles.person_id \) DESC/
|
|
545
598
|
)
|
|
546
599
|
end
|
|
600
|
+
|
|
601
|
+
context 'case insensitive sorting' do
|
|
602
|
+
it 'allows sort by desc' do
|
|
603
|
+
search = Person.ransack(sorts: ['name_case_insensitive desc'])
|
|
604
|
+
expect(search.result.to_sql).to match /ORDER BY LOWER(.*) DESC/
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
it 'allows sort by asc' do
|
|
608
|
+
search = Person.ransack(sorts: ['name_case_insensitive asc'])
|
|
609
|
+
expect(search.result.to_sql).to match /ORDER BY LOWER(.*) ASC/
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
context 'regular sorting' do
|
|
614
|
+
it 'allows sort by desc' do
|
|
615
|
+
search = Person.ransack(sorts: ['name desc'])
|
|
616
|
+
expect(search.result.to_sql).to match /ORDER BY .* DESC/
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
it 'allows sort by asc' do
|
|
620
|
+
search = Person.ransack(sorts: ['name asc'])
|
|
621
|
+
expect(search.result.to_sql).to match /ORDER BY .* ASC/
|
|
622
|
+
end
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
context 'sorting by a scope' do
|
|
626
|
+
it 'applies the correct scope' do
|
|
627
|
+
search = Person.ransack(sorts: ['reverse_name asc'])
|
|
628
|
+
expect(search.result.to_sql).to include("ORDER BY REVERSE(name) ASC")
|
|
629
|
+
end
|
|
630
|
+
end
|
|
547
631
|
end
|
|
548
632
|
|
|
549
633
|
describe '#ransackable_attributes' do
|
|
@@ -613,6 +697,16 @@ module Ransack
|
|
|
613
697
|
it { should eq [] }
|
|
614
698
|
end
|
|
615
699
|
|
|
700
|
+
describe '#ransackable_scopes_skip_sanitize_args' do
|
|
701
|
+
subject { Person.ransackable_scopes_skip_sanitize_args }
|
|
702
|
+
|
|
703
|
+
it { should eq [] }
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
private
|
|
707
|
+
def rails7_and_mysql
|
|
708
|
+
::ActiveRecord::VERSION::MAJOR >= 7 && ENV['DB'] == 'mysql'
|
|
709
|
+
end
|
|
616
710
|
end
|
|
617
711
|
end
|
|
618
712
|
end
|
|
@@ -9,9 +9,7 @@ module Ransack
|
|
|
9
9
|
describe Context do
|
|
10
10
|
subject { Context.new(Person) }
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
it 'has an Active Record alias tracker method',
|
|
14
|
-
if: AR_version >= '3.1' do
|
|
12
|
+
it 'has an Active Record alias tracker method' do
|
|
15
13
|
expect(subject.alias_tracker)
|
|
16
14
|
.to be_an ::ActiveRecord::Associations::AliasTracker
|
|
17
15
|
end
|
|
@@ -41,6 +39,66 @@ module Ransack
|
|
|
41
39
|
end
|
|
42
40
|
end
|
|
43
41
|
|
|
42
|
+
describe '#build_correlated_subquery' do
|
|
43
|
+
it 'build correlated subquery for Root STI model' do
|
|
44
|
+
search = Search.new(Person, { articles_title_not_eq: 'some_title' }, context: subject)
|
|
45
|
+
attribute = search.conditions.first.attributes.first
|
|
46
|
+
constraints = subject.build_correlated_subquery(attribute.parent).constraints
|
|
47
|
+
constraint = constraints.first
|
|
48
|
+
|
|
49
|
+
expect(constraints.length).to eql 1
|
|
50
|
+
expect(constraint.left.name).to eql 'person_id'
|
|
51
|
+
expect(constraint.left.relation.name).to eql 'articles'
|
|
52
|
+
expect(constraint.right.name).to eql 'id'
|
|
53
|
+
expect(constraint.right.relation.name).to eql 'people'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'build correlated subquery for Child STI model when predicate is not_eq' do
|
|
57
|
+
search = Search.new(Person, { story_articles_title_not_eq: 'some_title' }, context: subject)
|
|
58
|
+
attribute = search.conditions.first.attributes.first
|
|
59
|
+
constraints = subject.build_correlated_subquery(attribute.parent).constraints
|
|
60
|
+
constraint = constraints.first
|
|
61
|
+
|
|
62
|
+
expect(constraints.length).to eql 1
|
|
63
|
+
expect(constraint.left.relation.name).to eql 'articles'
|
|
64
|
+
expect(constraint.left.name).to eql 'person_id'
|
|
65
|
+
expect(constraint.right.relation.name).to eql 'people'
|
|
66
|
+
expect(constraint.right.name).to eql 'id'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'build correlated subquery for Child STI model when predicate is eq' do
|
|
70
|
+
search = Search.new(Person, { story_articles_title_not_eq: 'some_title' }, context: subject)
|
|
71
|
+
attribute = search.conditions.first.attributes.first
|
|
72
|
+
constraints = subject.build_correlated_subquery(attribute.parent).constraints
|
|
73
|
+
constraint = constraints.first
|
|
74
|
+
|
|
75
|
+
expect(constraints.length).to eql 1
|
|
76
|
+
expect(constraint.left.relation.name).to eql 'articles'
|
|
77
|
+
expect(constraint.left.name).to eql 'person_id'
|
|
78
|
+
expect(constraint.right.relation.name).to eql 'people'
|
|
79
|
+
expect(constraint.right.name).to eql 'id'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'build correlated subquery for multiple conditions (default scope)' do
|
|
83
|
+
search = Search.new(Person, { comments_body_not_eq: 'some_title' })
|
|
84
|
+
|
|
85
|
+
# Was
|
|
86
|
+
# SELECT "people".* FROM "people" WHERE "people"."id" NOT IN (
|
|
87
|
+
# SELECT "comments"."disabled" FROM "comments"
|
|
88
|
+
# WHERE "comments"."disabled" = "people"."id"
|
|
89
|
+
# AND NOT ("comments"."body" != 'some_title')
|
|
90
|
+
# ) ORDER BY "people"."id" DESC
|
|
91
|
+
# Should Be
|
|
92
|
+
# SELECT "people".* FROM "people" WHERE "people"."id" NOT IN (
|
|
93
|
+
# SELECT "comments"."person_id" FROM "comments"
|
|
94
|
+
# WHERE "comments"."person_id" = "people"."id"
|
|
95
|
+
# AND NOT ("comments"."body" != 'some_title')
|
|
96
|
+
# ) ORDER BY "people"."id" DESC
|
|
97
|
+
|
|
98
|
+
expect(search.result.to_sql).to match /.comments.\..person_id. = .people.\..id./
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
44
102
|
describe 'sharing context across searches' do
|
|
45
103
|
let(:shared_context) { Context.for(Person) }
|
|
46
104
|
|
|
@@ -51,34 +109,15 @@ module Ransack
|
|
|
51
109
|
context: shared_context)
|
|
52
110
|
end
|
|
53
111
|
|
|
54
|
-
describe '#join_associations', if: AR_version <= '4.0' do
|
|
55
|
-
it 'returns dependent join associations for all searches run
|
|
56
|
-
against the context' do
|
|
57
|
-
parents, children = shared_context.join_associations
|
|
58
|
-
|
|
59
|
-
expect(children.aliased_table_name).to eq "children_people"
|
|
60
|
-
expect(parents.aliased_table_name).to eq "parents_people"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it 'can be rejoined to execute a valid query' do
|
|
64
|
-
parents, children = shared_context.join_associations
|
|
65
|
-
|
|
66
|
-
expect { Person.joins(parents).joins(children).to_a }
|
|
67
|
-
.to_not raise_error
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
112
|
describe '#join_sources' do
|
|
72
|
-
# FIXME: fix this test for Rails 4.2 and 5.0.
|
|
73
113
|
it 'returns dependent arel join nodes for all searches run against
|
|
74
|
-
the context'
|
|
114
|
+
the context' do
|
|
75
115
|
parents, children = shared_context.join_sources
|
|
76
116
|
expect(children.left.name).to eq "children_people"
|
|
77
117
|
expect(parents.left.name).to eq "parents_people"
|
|
78
118
|
end
|
|
79
119
|
|
|
80
|
-
it 'can be rejoined to execute a valid query'
|
|
81
|
-
if: AR_version >= '3.1' do
|
|
120
|
+
it 'can be rejoined to execute a valid query' do
|
|
82
121
|
parents, children = shared_context.join_sources
|
|
83
122
|
|
|
84
123
|
expect { Person.joins(parents).joins(children).to_a }
|
|
@@ -45,6 +45,20 @@ module Ransack
|
|
|
45
45
|
Ransack.options = default
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
it 'should have default value for strip_whitespace' do
|
|
49
|
+
expect(Ransack.options[:strip_whitespace]).to eq true
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'changes default search key parameter' do
|
|
53
|
+
default = Ransack.options.clone
|
|
54
|
+
|
|
55
|
+
Ransack.configure { |c| c.strip_whitespace = false }
|
|
56
|
+
|
|
57
|
+
expect(Ransack.options[:strip_whitespace]).to eq false
|
|
58
|
+
|
|
59
|
+
Ransack.options = default
|
|
60
|
+
end
|
|
61
|
+
|
|
48
62
|
it 'should have default values for arrows' do
|
|
49
63
|
expect(Ransack.options[:up_arrow]).to eq '▼'
|
|
50
64
|
expect(Ransack.options[:down_arrow]).to eq '▲'
|
|
@@ -173,5 +187,15 @@ module Ransack
|
|
|
173
187
|
.to eq false
|
|
174
188
|
end
|
|
175
189
|
end
|
|
190
|
+
|
|
191
|
+
it "PG's sort option", if: ::ActiveRecord::Base.connection.adapter_name == "PostgreSQL" do
|
|
192
|
+
default = Ransack.options.clone
|
|
193
|
+
|
|
194
|
+
Ransack.configure { |c| c.postgres_fields_sort_option = :nulls_first }
|
|
195
|
+
|
|
196
|
+
expect(Ransack.options[:postgres_fields_sort_option]).to eq :nulls_first
|
|
197
|
+
|
|
198
|
+
Ransack.options = default
|
|
199
|
+
end
|
|
176
200
|
end
|
|
177
201
|
end
|
|
@@ -21,11 +21,7 @@ module Ransack
|
|
|
21
21
|
@controller.view_context.search_form_for(@s) { |f| @f = f }
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
it 'selects previously-entered time values with datetime_select'
|
|
25
|
-
unless: (
|
|
26
|
-
RUBY_VERSION >= '2.3' &&
|
|
27
|
-
::ActiveRecord::VERSION::STRING.first(3) < '3.2'
|
|
28
|
-
) do
|
|
24
|
+
it 'selects previously-entered time values with datetime_select' do
|
|
29
25
|
date_values = %w(2011 1 2 03 04 05)
|
|
30
26
|
# @s.created_at_eq = date_values # This works in Rails 4.x but not 3.x
|
|
31
27
|
@s.created_at_eq = [2011, 1, 2, 3, 4, 5] # so we have to do this
|
|
@@ -75,11 +71,7 @@ module Ransack
|
|
|
75
71
|
describe '#sort_link' do
|
|
76
72
|
it 'sort_link for ransack attribute' do
|
|
77
73
|
sort_link = @f.sort_link :name, :controller => 'people'
|
|
78
|
-
|
|
79
|
-
expect(sort_link).to match /people\?q%5Bs%5D=name\+asc/
|
|
80
|
-
else
|
|
81
|
-
expect(sort_link).to match /people\?q(%5B|\[)s(%5D|\])=name\+asc/
|
|
82
|
-
end
|
|
74
|
+
expect(sort_link).to match /people\?q(%5B|\[)s(%5D|\])=name\+asc/
|
|
83
75
|
expect(sort_link).to match /sort_link/
|
|
84
76
|
expect(sort_link).to match /Full Name<\/a>/
|
|
85
77
|
end
|
|
@@ -171,11 +163,7 @@ module Ransack
|
|
|
171
163
|
# Starting from Rails 4.2, the date_select html attributes are no longer
|
|
172
164
|
# `sort`ed (for a speed gain), so the tests have to be different:
|
|
173
165
|
def date_select_html(val)
|
|
174
|
-
|
|
175
|
-
%(<option value="#{val}" selected="selected">#{val}</option>)
|
|
176
|
-
else
|
|
177
|
-
%(<option selected="selected" value="#{val}">#{val}</option>)
|
|
178
|
-
end
|
|
166
|
+
%(<option value="#{val}" selected="selected">#{val}</option>)
|
|
179
167
|
end
|
|
180
168
|
|
|
181
169
|
end
|