ransack 2.3.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +3 -0
- data/.github/SECURITY.md +12 -0
- data/.github/workflows/codeql.yml +72 -0
- data/.github/workflows/cronjob.yml +99 -0
- data/.github/workflows/deploy.yml +35 -0
- data/.github/workflows/rubocop.yml +20 -0
- data/.github/workflows/test-deploy.yml +29 -0
- data/.github/workflows/test.yml +131 -0
- data/.nojekyll +0 -0
- data/.rubocop.yml +50 -0
- data/CHANGELOG.md +263 -1
- data/CONTRIBUTING.md +51 -29
- data/Gemfile +24 -10
- data/README.md +49 -917
- data/bug_report_templates/test-ransack-scope-and-column-same-name.rb +78 -0
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +75 -0
- data/docs/.gitignore +19 -0
- data/docs/.nojekyll +0 -0
- data/docs/babel.config.js +3 -0
- data/docs/blog/2022-03-27-ransack-3.0.0.md +20 -0
- data/docs/docs/getting-started/_category_.json +4 -0
- data/docs/docs/getting-started/advanced-mode.md +46 -0
- data/docs/docs/getting-started/configuration.md +47 -0
- data/docs/docs/getting-started/search-matches.md +67 -0
- data/docs/docs/getting-started/simple-mode.md +288 -0
- data/docs/docs/getting-started/sorting.md +71 -0
- data/docs/docs/getting-started/using-predicates.md +282 -0
- data/docs/docs/going-further/_category_.json +4 -0
- data/docs/docs/going-further/acts-as-taggable-on.md +114 -0
- data/docs/docs/going-further/associations.md +70 -0
- data/docs/docs/going-further/custom-predicates.md +52 -0
- data/docs/docs/going-further/documentation.md +43 -0
- data/docs/docs/going-further/exporting-to-csv.md +49 -0
- data/docs/docs/going-further/external-guides.md +57 -0
- data/docs/docs/going-further/form-customisation.md +63 -0
- data/docs/docs/going-further/i18n.md +53 -0
- data/docs/docs/going-further/img/create_release.png +0 -0
- data/docs/docs/going-further/merging-searches.md +41 -0
- data/docs/docs/going-further/other-notes.md +428 -0
- data/docs/docs/going-further/polymorphic-search.md +46 -0
- data/docs/docs/going-further/ransackers.md +331 -0
- data/docs/docs/going-further/release_process.md +36 -0
- data/docs/docs/going-further/saving-queries.md +82 -0
- data/docs/docs/going-further/searching-postgres.md +57 -0
- data/docs/docs/going-further/wiki-contributors.md +82 -0
- data/docs/docs/intro.md +99 -0
- data/docs/docusaurus.config.js +120 -0
- data/docs/package.json +42 -0
- data/docs/sidebars.js +31 -0
- data/docs/src/components/HomepageFeatures/index.js +64 -0
- data/docs/src/components/HomepageFeatures/styles.module.css +11 -0
- data/docs/src/css/custom.css +39 -0
- data/docs/src/pages/index.module.css +23 -0
- data/docs/src/pages/markdown-page.md +7 -0
- data/docs/static/.nojekyll +0 -0
- data/docs/static/img/docusaurus.png +0 -0
- data/docs/static/img/favicon.ico +0 -0
- data/docs/static/img/logo.svg +1 -0
- data/docs/static/img/tutorial/docsVersionDropdown.png +0 -0
- data/docs/static/img/tutorial/localeDropdown.png +0 -0
- data/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
- data/docs/static/img/undraw_docusaurus_react.svg +170 -0
- data/docs/static/img/undraw_docusaurus_tree.svg +40 -0
- data/docs/yarn.lock +8879 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +70 -0
- data/{polyamorous/lib/polyamorous/activerecord_6.0_ruby_2 → lib/polyamorous/activerecord_6.1_ruby_2}/join_dependency.rb +33 -12
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_7.0_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/join_dependency.rb +1 -0
- data/lib/polyamorous/activerecord_7.1_ruby_2/reflection.rb +1 -0
- data/{polyamorous/lib → lib/polyamorous}/polyamorous.rb +3 -8
- data/lib/ransack/adapters/active_record/base.rb +83 -10
- data/lib/ransack/adapters/active_record/context.rb +61 -116
- data/lib/ransack/configuration.rb +53 -10
- data/lib/ransack/constants.rb +126 -7
- data/lib/ransack/context.rb +34 -5
- data/lib/ransack/helpers/form_builder.rb +11 -17
- data/lib/ransack/helpers/form_helper.rb +14 -5
- data/lib/ransack/helpers.rb +1 -1
- data/lib/ransack/locale/sk.yml +70 -0
- data/lib/ransack/locale/sv.yml +70 -0
- data/lib/ransack/nodes/attribute.rb +3 -3
- data/lib/ransack/nodes/condition.rb +87 -8
- data/lib/ransack/nodes/grouping.rb +4 -4
- data/lib/ransack/nodes/node.rb +1 -1
- data/lib/ransack/nodes/sort.rb +3 -3
- data/lib/ransack/nodes/value.rb +3 -3
- data/lib/ransack/predicate.rb +3 -2
- data/lib/ransack/ransacker.rb +1 -1
- data/lib/ransack/search.rb +15 -7
- data/lib/ransack/translate.rb +6 -6
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +38 -2
- data/lib/ransack.rb +6 -10
- data/ransack.gemspec +9 -24
- data/spec/blueprints/articles.rb +1 -1
- data/spec/blueprints/comments.rb +1 -1
- data/spec/blueprints/notes.rb +1 -1
- data/spec/blueprints/tags.rb +1 -1
- data/spec/console.rb +5 -5
- data/spec/helpers/polyamorous_helper.rb +2 -17
- data/spec/helpers/ransack_helper.rb +1 -1
- data/spec/polyamorous/activerecord_compatibility_spec.rb +15 -0
- data/spec/{ransack → polyamorous}/join_association_spec.rb +3 -1
- data/spec/{ransack → polyamorous}/join_dependency_spec.rb +0 -16
- data/spec/ransack/adapters/active_record/base_spec.rb +125 -16
- data/spec/ransack/adapters/active_record/context_spec.rb +19 -18
- data/spec/ransack/configuration_spec.rb +33 -9
- data/spec/ransack/helpers/form_builder_spec.rb +8 -8
- data/spec/ransack/helpers/form_helper_spec.rb +109 -20
- data/spec/ransack/nodes/condition_spec.rb +37 -0
- data/spec/ransack/nodes/grouping_spec.rb +2 -2
- data/spec/ransack/nodes/value_spec.rb +115 -0
- data/spec/ransack/predicate_spec.rb +75 -2
- data/spec/ransack/search_spec.rb +239 -38
- data/spec/ransack/translate_spec.rb +1 -1
- data/spec/spec_helper.rb +9 -5
- data/spec/support/schema.rb +111 -12
- metadata +105 -195
- data/.travis.yml +0 -49
- data/lib/ransack/adapters/active_record/ransack/constants.rb +0 -116
- data/lib/ransack/adapters/active_record/ransack/context.rb +0 -60
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +0 -61
- data/lib/ransack/adapters/active_record/ransack/translate.rb +0 -8
- data/lib/ransack/adapters/active_record/ransack/visitor.rb +0 -47
- data/lib/ransack/adapters.rb +0 -64
- data/lib/ransack/nodes.rb +0 -8
- data/polyamorous/lib/polyamorous/activerecord_5.0_ruby_2/join_association.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +0 -31
- data/polyamorous/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +0 -112
- data/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb +0 -31
- data/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +0 -112
- data/polyamorous/lib/polyamorous/activerecord_5.2.0_ruby_2/reflection.rb +0 -12
- data/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb +0 -22
- data/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb +0 -81
- data/polyamorous/lib/polyamorous/activerecord_5.2.1_ruby_2/reflection.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +0 -2
- data/polyamorous/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +0 -2
- data/polyamorous/lib/polyamorous/version.rb +0 -3
- data/polyamorous/polyamorous.gemspec +0 -35
- /data/{logo → docs/static/logo}/ransack-h.png +0 -0
- /data/{logo → docs/static/logo}/ransack-h.svg +0 -0
- /data/{logo → docs/static/logo}/ransack-v.png +0 -0
- /data/{logo → docs/static/logo}/ransack-v.svg +0 -0
- /data/{logo → docs/static/logo}/ransack.png +0 -0
- /data/{logo → docs/static/logo}/ransack.svg +0 -0
- /data/{polyamorous/lib → lib}/polyamorous/join.rb +0 -0
- /data/{polyamorous/lib → lib}/polyamorous/swapping_reflection_class.rb +0 -0
- /data/{polyamorous/lib → lib}/polyamorous/tree_node.rb +0 -0
- /data/lib/ransack/{adapters/active_record.rb → active_record.rb} +0 -0
- /data/spec/{ransack → polyamorous}/join_spec.rb +0 -0
|
@@ -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 }
|
|
@@ -44,12 +43,12 @@ module Ransack
|
|
|
44
43
|
|
|
45
44
|
it 'applies stringy boolean scopes with true value in an array' do
|
|
46
45
|
s = Person.ransack('of_age' => ['true'])
|
|
47
|
-
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')
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
it 'applies stringy boolean scopes with false value in an array' do
|
|
51
50
|
s = Person.ransack('of_age' => ['false'])
|
|
52
|
-
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')
|
|
53
52
|
end
|
|
54
53
|
|
|
55
54
|
it 'ignores unlisted scopes' do
|
|
@@ -69,15 +68,25 @@ module Ransack
|
|
|
69
68
|
|
|
70
69
|
it 'passes values to scopes' do
|
|
71
70
|
s = Person.ransack('over_age' => 18)
|
|
72
|
-
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')
|
|
73
72
|
end
|
|
74
73
|
|
|
75
74
|
it 'chains scopes' do
|
|
76
75
|
s = Person.ransack('over_age' => 18, 'active' => true)
|
|
77
|
-
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')
|
|
78
77
|
expect(s.result.to_sql).to (include 'active = 1')
|
|
79
78
|
end
|
|
80
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
|
+
|
|
81
90
|
context "with sanitize_custom_scope_booleans set to false" do
|
|
82
91
|
before(:all) do
|
|
83
92
|
Ransack.configure { |c| c.sanitize_custom_scope_booleans = false }
|
|
@@ -89,12 +98,12 @@ module Ransack
|
|
|
89
98
|
|
|
90
99
|
it 'passes true values to scopes' do
|
|
91
100
|
s = Person.ransack('over_age' => 1)
|
|
92
|
-
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')
|
|
93
102
|
end
|
|
94
103
|
|
|
95
104
|
it 'passes false values to scopes' do
|
|
96
105
|
s = Person.ransack('over_age' => 0)
|
|
97
|
-
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')
|
|
98
107
|
end
|
|
99
108
|
end
|
|
100
109
|
|
|
@@ -107,12 +116,12 @@ module Ransack
|
|
|
107
116
|
|
|
108
117
|
it 'passes true values to scopes' do
|
|
109
118
|
s = Person.ransack('over_age' => 1)
|
|
110
|
-
expect(s.result.to_sql).to (include 'age > 1')
|
|
119
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '1'} : 'age > 1')
|
|
111
120
|
end
|
|
112
121
|
|
|
113
122
|
it 'passes false values to scopes' do
|
|
114
123
|
s = Person.ransack('over_age' => 0)
|
|
115
|
-
expect(s.result.to_sql).to (include 'age > 0')
|
|
124
|
+
expect(s.result.to_sql).to (include rails7_and_mysql ? %q{age > '0'} : 'age > 0')
|
|
116
125
|
end
|
|
117
126
|
end
|
|
118
127
|
|
|
@@ -122,12 +131,32 @@ module Ransack
|
|
|
122
131
|
expect { Person.ransack('') }.to_not raise_error
|
|
123
132
|
end
|
|
124
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
|
+
|
|
125
138
|
it 'does not modify the parameters' do
|
|
126
139
|
params = { name_eq: '' }
|
|
127
140
|
expect { Person.ransack(params) }.not_to change { params }
|
|
128
141
|
end
|
|
129
142
|
end
|
|
130
143
|
|
|
144
|
+
context 'has_one through associations' do
|
|
145
|
+
let(:address) { Address.create!(city: 'Boston') }
|
|
146
|
+
let(:org) { Organization.create!(name: 'Testorg', address: address) }
|
|
147
|
+
let!(:employee) { Employee.create!(name: 'Ernie', organization: org) }
|
|
148
|
+
|
|
149
|
+
it 'works when has_one through association is first' do
|
|
150
|
+
s = Employee.ransack(address_city_eq: 'Boston', organization_name_eq: 'Testorg')
|
|
151
|
+
expect(s.result.to_a).to include(employee)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'works when has_one through association is last' do
|
|
155
|
+
s = Employee.ransack(organization_name_eq: 'Testorg', address_city_eq: 'Boston')
|
|
156
|
+
expect(s.result.to_a).to include(employee)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
131
160
|
context 'negative conditions on HABTM associations' do
|
|
132
161
|
let(:medieval) { Tag.create!(name: 'Medieval') }
|
|
133
162
|
let(:fantasy) { Tag.create!(name: 'Fantasy') }
|
|
@@ -143,14 +172,12 @@ module Ransack
|
|
|
143
172
|
it 'removes redundant joins from top query' do
|
|
144
173
|
s = Article.ransack(tags_name_not_eq: "Fantasy")
|
|
145
174
|
sql = s.result.to_sql
|
|
146
|
-
|
|
147
175
|
expect(sql).to_not include('LEFT OUTER JOIN')
|
|
148
176
|
end
|
|
149
177
|
|
|
150
178
|
it 'handles != for single values' do
|
|
151
179
|
s = Article.ransack(tags_name_not_eq: "Fantasy")
|
|
152
180
|
articles = s.result.to_a
|
|
153
|
-
|
|
154
181
|
expect(articles).to include marco
|
|
155
182
|
expect(articles).to_not include arthur
|
|
156
183
|
end
|
|
@@ -267,10 +294,12 @@ module Ransack
|
|
|
267
294
|
# end
|
|
268
295
|
|
|
269
296
|
it 'creates ransack attributes' do
|
|
297
|
+
person = Person.create!(name: 'Aric Smith')
|
|
298
|
+
|
|
270
299
|
s = Person.ransack(reversed_name_eq: 'htimS cirA')
|
|
271
300
|
expect(s.result.size).to eq(1)
|
|
272
301
|
|
|
273
|
-
expect(s.result.first).to eq
|
|
302
|
+
expect(s.result.first).to eq person
|
|
274
303
|
end
|
|
275
304
|
|
|
276
305
|
it 'can be accessed through associations' do
|
|
@@ -310,7 +339,11 @@ module Ransack
|
|
|
310
339
|
end
|
|
311
340
|
|
|
312
341
|
it 'should function correctly with a multi-parameter attribute' do
|
|
313
|
-
::ActiveRecord::
|
|
342
|
+
if ::ActiveRecord::VERSION::MAJOR >= 7
|
|
343
|
+
::ActiveRecord.default_timezone = :utc
|
|
344
|
+
else
|
|
345
|
+
::ActiveRecord::Base.default_timezone = :utc
|
|
346
|
+
end
|
|
314
347
|
Time.zone = 'UTC'
|
|
315
348
|
|
|
316
349
|
date = Date.current
|
|
@@ -460,9 +493,9 @@ module Ransack
|
|
|
460
493
|
Comment.create(article: Article.create(title: 'Avenger'), person: Person.create(salary: 100_000)),
|
|
461
494
|
Comment.create(article: Article.create(title: 'Avenge'), person: Person.create(salary: 50_000)),
|
|
462
495
|
]
|
|
463
|
-
expect(Comment.ransack(article_title_cont: 'aven',s: 'person_salary desc').result).to eq(comments)
|
|
496
|
+
expect(Comment.ransack(article_title_cont: 'aven', s: 'person_salary desc').result).to eq(comments)
|
|
464
497
|
expect(Comment.joins(:person).ransack(s: 'persons_salarydesc', article_title_cont: 'aven').result).to eq(comments)
|
|
465
|
-
expect(Comment.joins(:person).ransack(article_title_cont: 'aven',s: 'persons_salary desc').result).to eq(comments)
|
|
498
|
+
expect(Comment.joins(:person).ransack(article_title_cont: 'aven', s: 'persons_salary desc').result).to eq(comments)
|
|
466
499
|
end
|
|
467
500
|
|
|
468
501
|
it 'allows sort by `only_sort` field' do
|
|
@@ -541,7 +574,6 @@ module Ransack
|
|
|
541
574
|
)
|
|
542
575
|
end
|
|
543
576
|
|
|
544
|
-
|
|
545
577
|
it 'should allow passing ransacker arguments to a ransacker' do
|
|
546
578
|
s = Person.ransack(
|
|
547
579
|
c: [{
|
|
@@ -641,6 +673,37 @@ module Ransack
|
|
|
641
673
|
it { should_not include 'only_sort' }
|
|
642
674
|
it { should include 'only_admin' }
|
|
643
675
|
end
|
|
676
|
+
|
|
677
|
+
context 'when not defined in model, nor in ApplicationRecord' do
|
|
678
|
+
subject { Article.ransackable_attributes }
|
|
679
|
+
|
|
680
|
+
it "raises a helpful error" do
|
|
681
|
+
without_application_record_method(:ransackable_attributes) do
|
|
682
|
+
expect { subject }.to raise_error(RuntimeError, /Ransack needs Article attributes explicitly allowlisted/)
|
|
683
|
+
end
|
|
684
|
+
end
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
context 'when defined only in model by delegating to super' do
|
|
688
|
+
subject { Article.ransackable_attributes }
|
|
689
|
+
|
|
690
|
+
around do |example|
|
|
691
|
+
Article.singleton_class.define_method(:ransackable_attributes) do
|
|
692
|
+
super(nil) - super(nil)
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
example.run
|
|
696
|
+
ensure
|
|
697
|
+
Article.singleton_class.remove_method(:ransackable_attributes)
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
it "returns the allowlist in the model, and warns" do
|
|
701
|
+
without_application_record_method(:ransackable_attributes) do
|
|
702
|
+
expect { subject }.to output(/Ransack's builtin `ransackable_attributes` method is deprecated/).to_stderr
|
|
703
|
+
expect(subject).to be_empty
|
|
704
|
+
end
|
|
705
|
+
end
|
|
706
|
+
end
|
|
644
707
|
end
|
|
645
708
|
|
|
646
709
|
describe '#ransortable_attributes' do
|
|
@@ -673,6 +736,37 @@ module Ransack
|
|
|
673
736
|
it { should include 'parent' }
|
|
674
737
|
it { should include 'children' }
|
|
675
738
|
it { should include 'articles' }
|
|
739
|
+
|
|
740
|
+
context 'when not defined in model, nor in ApplicationRecord' do
|
|
741
|
+
subject { Article.ransackable_associations }
|
|
742
|
+
|
|
743
|
+
it "raises a helpful error" do
|
|
744
|
+
without_application_record_method(:ransackable_associations) do
|
|
745
|
+
expect { subject }.to raise_error(RuntimeError, /Ransack needs Article associations explicitly allowlisted/)
|
|
746
|
+
end
|
|
747
|
+
end
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
context 'when defined only in model by delegating to super' do
|
|
751
|
+
subject { Article.ransackable_associations }
|
|
752
|
+
|
|
753
|
+
around do |example|
|
|
754
|
+
Article.singleton_class.define_method(:ransackable_associations) do
|
|
755
|
+
super(nil) - super(nil)
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
example.run
|
|
759
|
+
ensure
|
|
760
|
+
Article.singleton_class.remove_method(:ransackable_associations)
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
it "returns the allowlist in the model, and warns" do
|
|
764
|
+
without_application_record_method(:ransackable_associations) do
|
|
765
|
+
expect { subject }.to output(/Ransack's builtin `ransackable_associations` method is deprecated/).to_stderr
|
|
766
|
+
expect(subject).to be_empty
|
|
767
|
+
end
|
|
768
|
+
end
|
|
769
|
+
end
|
|
676
770
|
end
|
|
677
771
|
|
|
678
772
|
describe '#ransackable_scopes' do
|
|
@@ -687,6 +781,21 @@ module Ransack
|
|
|
687
781
|
it { should eq [] }
|
|
688
782
|
end
|
|
689
783
|
|
|
784
|
+
private
|
|
785
|
+
|
|
786
|
+
def without_application_record_method(method)
|
|
787
|
+
ApplicationRecord.singleton_class.alias_method :"original_#{method}", :"#{method}"
|
|
788
|
+
ApplicationRecord.singleton_class.remove_method :"#{method}"
|
|
789
|
+
|
|
790
|
+
yield
|
|
791
|
+
ensure
|
|
792
|
+
ApplicationRecord.singleton_class.alias_method :"#{method}", :"original_#{method}"
|
|
793
|
+
ApplicationRecord.singleton_class.remove_method :"original_#{method}"
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
def rails7_and_mysql
|
|
797
|
+
::ActiveRecord::VERSION::MAJOR >= 7 && ENV['DB'] == 'mysql'
|
|
798
|
+
end
|
|
690
799
|
end
|
|
691
800
|
end
|
|
692
801
|
end
|
|
@@ -9,7 +9,6 @@ module Ransack
|
|
|
9
9
|
describe Context do
|
|
10
10
|
subject { Context.new(Person) }
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
it 'has an Active Record alias tracker method' do
|
|
14
13
|
expect(subject.alias_tracker)
|
|
15
14
|
.to be_an ::ActiveRecord::Associations::AliasTracker
|
|
@@ -79,6 +78,25 @@ module Ransack
|
|
|
79
78
|
expect(constraint.right.relation.name).to eql 'people'
|
|
80
79
|
expect(constraint.right.name).to eql 'id'
|
|
81
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
|
|
82
100
|
end
|
|
83
101
|
|
|
84
102
|
describe 'sharing context across searches' do
|
|
@@ -91,23 +109,6 @@ module Ransack
|
|
|
91
109
|
context: shared_context)
|
|
92
110
|
end
|
|
93
111
|
|
|
94
|
-
describe '#join_associations', if: AR_version <= '4.0' do
|
|
95
|
-
it 'returns dependent join associations for all searches run
|
|
96
|
-
against the context' do
|
|
97
|
-
parents, children = shared_context.join_associations
|
|
98
|
-
|
|
99
|
-
expect(children.aliased_table_name).to eq "children_people"
|
|
100
|
-
expect(parents.aliased_table_name).to eq "parents_people"
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
it 'can be rejoined to execute a valid query' do
|
|
104
|
-
parents, children = shared_context.join_associations
|
|
105
|
-
|
|
106
|
-
expect { Person.joins(parents).joins(children).to_a }
|
|
107
|
-
.to_not raise_error
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
112
|
describe '#join_sources' do
|
|
112
113
|
it 'returns dependent arel join nodes for all searches run against
|
|
113
114
|
the context' do
|
|
@@ -20,7 +20,7 @@ module Ransack
|
|
|
20
20
|
Ransack.configure do |config|
|
|
21
21
|
config.add_predicate(
|
|
22
22
|
:test_predicate_without_compound,
|
|
23
|
-
:
|
|
23
|
+
compounds: false
|
|
24
24
|
)
|
|
25
25
|
end
|
|
26
26
|
expect(Ransack.predicates)
|
|
@@ -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 '▲'
|
|
@@ -124,8 +138,8 @@ module Ransack
|
|
|
124
138
|
Ransack.configure do |config|
|
|
125
139
|
config.add_predicate(
|
|
126
140
|
:test_array_predicate,
|
|
127
|
-
:
|
|
128
|
-
:
|
|
141
|
+
wants_array: true,
|
|
142
|
+
compounds: true
|
|
129
143
|
)
|
|
130
144
|
end
|
|
131
145
|
|
|
@@ -139,11 +153,11 @@ module Ransack
|
|
|
139
153
|
Ransack.configure do |config|
|
|
140
154
|
config.add_predicate(
|
|
141
155
|
:test_in_predicate,
|
|
142
|
-
:
|
|
156
|
+
arel_predicate: 'in'
|
|
143
157
|
)
|
|
144
158
|
config.add_predicate(
|
|
145
159
|
:test_not_in_predicate,
|
|
146
|
-
:
|
|
160
|
+
arel_predicate: 'not_in'
|
|
147
161
|
)
|
|
148
162
|
end
|
|
149
163
|
|
|
@@ -157,13 +171,13 @@ module Ransack
|
|
|
157
171
|
Ransack.configure do |config|
|
|
158
172
|
config.add_predicate(
|
|
159
173
|
:test_in_predicate_no_array,
|
|
160
|
-
:
|
|
161
|
-
:
|
|
174
|
+
arel_predicate: 'in',
|
|
175
|
+
wants_array: false
|
|
162
176
|
)
|
|
163
177
|
config.add_predicate(
|
|
164
178
|
:test_not_in_predicate_no_array,
|
|
165
|
-
:
|
|
166
|
-
:
|
|
179
|
+
arel_predicate: 'not_in',
|
|
180
|
+
wants_array: false
|
|
167
181
|
)
|
|
168
182
|
end
|
|
169
183
|
|
|
@@ -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
|
|
@@ -26,7 +26,7 @@ module Ransack
|
|
|
26
26
|
# @s.created_at_eq = date_values # This works in Rails 4.x but not 3.x
|
|
27
27
|
@s.created_at_eq = [2011, 1, 2, 3, 4, 5] # so we have to do this
|
|
28
28
|
html = @f.datetime_select(
|
|
29
|
-
:created_at_eq, :
|
|
29
|
+
:created_at_eq, use_month_numbers: true, include_seconds: true
|
|
30
30
|
)
|
|
31
31
|
date_values.each { |val| expect(html).to include date_select_html(val) }
|
|
32
32
|
end
|
|
@@ -70,13 +70,13 @@ module Ransack
|
|
|
70
70
|
|
|
71
71
|
describe '#sort_link' do
|
|
72
72
|
it 'sort_link for ransack attribute' do
|
|
73
|
-
sort_link = @f.sort_link :name, :
|
|
73
|
+
sort_link = @f.sort_link :name, controller: 'people'
|
|
74
74
|
expect(sort_link).to match /people\?q(%5B|\[)s(%5D|\])=name\+asc/
|
|
75
75
|
expect(sort_link).to match /sort_link/
|
|
76
76
|
expect(sort_link).to match /Full Name<\/a>/
|
|
77
77
|
end
|
|
78
78
|
it 'sort_link for common attribute' do
|
|
79
|
-
sort_link = @f.sort_link :id, :
|
|
79
|
+
sort_link = @f.sort_link :id, controller: 'people'
|
|
80
80
|
expect(sort_link).to match /id<\/a>/
|
|
81
81
|
end
|
|
82
82
|
end
|
|
@@ -99,14 +99,14 @@ module Ransack
|
|
|
99
99
|
it 'returns ransackable attributes for associations with :associations' do
|
|
100
100
|
attributes = Person.ransackable_attributes +
|
|
101
101
|
Article.ransackable_attributes.map { |a| "articles_#{a}" }
|
|
102
|
-
html = @f.attribute_select(:
|
|
102
|
+
html = @f.attribute_select(associations: ['articles'])
|
|
103
103
|
expect(html.split(/\n/).size).to eq(attributes.size)
|
|
104
104
|
attributes.each do |attribute|
|
|
105
105
|
expect(html).to match /<option value="#{attribute}">/
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
it 'returns option groups for base and associations with :associations' do
|
|
109
|
-
html = @f.attribute_select(:
|
|
109
|
+
html = @f.attribute_select(associations: ['articles'])
|
|
110
110
|
[Person, Article].each do |model|
|
|
111
111
|
expect(html).to match /<optgroup label="#{model}">/
|
|
112
112
|
end
|
|
@@ -121,19 +121,19 @@ module Ransack
|
|
|
121
121
|
end
|
|
122
122
|
end
|
|
123
123
|
it 'filters predicates with single-value :only' do
|
|
124
|
-
html = @f.predicate_select :
|
|
124
|
+
html = @f.predicate_select only: 'eq'
|
|
125
125
|
Predicate.names.reject { |k| k =~ /^eq/ }.each do |key|
|
|
126
126
|
expect(html).not_to match /<option value="#{key}">/
|
|
127
127
|
end
|
|
128
128
|
end
|
|
129
129
|
it 'filters predicates with multi-value :only' do
|
|
130
|
-
html = @f.predicate_select :
|
|
130
|
+
html = @f.predicate_select only: [:eq, :lt]
|
|
131
131
|
Predicate.names.reject { |k| k =~ /^(eq|lt)/ }.each do |key|
|
|
132
132
|
expect(html).not_to match /<option value="#{key}">/
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
135
|
it 'excludes compounds when compounds: false' do
|
|
136
|
-
html = @f.predicate_select :
|
|
136
|
+
html = @f.predicate_select compounds: false
|
|
137
137
|
Predicate.names.select { |k| k =~ /_(any|all)$/ }.each do |key|
|
|
138
138
|
expect(html).not_to match /<option value="#{key}">/
|
|
139
139
|
end
|