ransack 3.2.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/codeql.yml +72 -0
- data/.github/workflows/test.yml +6 -8
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +51 -0
- data/CONTRIBUTING.md +33 -11
- data/Gemfile +9 -9
- data/README.md +4 -9
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +4 -0
- data/docs/docs/getting-started/advanced-mode.md +1 -1
- data/docs/docs/getting-started/search-matches.md +1 -1
- data/docs/docs/getting-started/simple-mode.md +6 -2
- data/docs/docs/going-further/acts-as-taggable-on.md +4 -4
- data/docs/docs/going-further/form-customisation.md +1 -1
- data/docs/docs/going-further/i18n.md +3 -3
- data/docs/docs/going-further/other-notes.md +1 -1
- data/docs/docs/going-further/saving-queries.md +1 -1
- data/docs/docs/going-further/searching-postgres.md +1 -1
- data/docs/package.json +7 -3
- data/docs/yarn.lock +2255 -1901
- data/lib/ransack/{adapters/active_record.rb → active_record.rb} +0 -0
- data/lib/ransack/adapters/active_record/base.rb +78 -7
- data/lib/ransack/configuration.rb +25 -12
- data/lib/ransack/constants.rb +125 -0
- data/lib/ransack/context.rb +34 -5
- data/lib/ransack/helpers/form_builder.rb +3 -3
- data/lib/ransack/helpers/form_helper.rb +3 -2
- data/lib/ransack/nodes/attribute.rb +2 -2
- data/lib/ransack/nodes/condition.rb +80 -7
- data/lib/ransack/nodes/grouping.rb +3 -3
- data/lib/ransack/nodes/node.rb +1 -1
- data/lib/ransack/nodes/value.rb +1 -1
- data/lib/ransack/predicate.rb +1 -1
- data/lib/ransack/ransacker.rb +1 -1
- data/lib/ransack/search.rb +9 -4
- data/lib/ransack/translate.rb +2 -2
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +38 -2
- data/lib/ransack.rb +3 -6
- data/spec/ransack/adapters/active_record/base_spec.rb +73 -0
- data/spec/ransack/configuration_spec.rb +9 -9
- data/spec/ransack/helpers/form_builder_spec.rb +8 -8
- data/spec/ransack/helpers/form_helper_spec.rb +36 -2
- data/spec/ransack/nodes/condition_spec.rb +24 -0
- data/spec/ransack/predicate_spec.rb +36 -1
- data/spec/ransack/translate_spec.rb +1 -1
- data/spec/support/schema.rb +27 -10
- metadata +5 -12
- data/lib/polyamorous.rb +0 -1
- data/lib/ransack/adapters/active_record/ransack/constants.rb +0 -128
- data/lib/ransack/adapters/active_record/ransack/context.rb +0 -56
- 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/lib/ransack/visitor.rb
CHANGED
@@ -26,7 +26,14 @@ module Ransack
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def visit_and(object)
|
29
|
-
|
29
|
+
nodes = object.values.map { |o| accept(o) }.compact
|
30
|
+
return nil unless nodes.size > 0
|
31
|
+
|
32
|
+
if nodes.size > 1
|
33
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::And.new(nodes))
|
34
|
+
else
|
35
|
+
nodes.first
|
36
|
+
end
|
30
37
|
end
|
31
38
|
|
32
39
|
def visit_or(object)
|
@@ -35,17 +42,46 @@ module Ransack
|
|
35
42
|
end
|
36
43
|
|
37
44
|
def quoted?(object)
|
38
|
-
|
45
|
+
case object
|
46
|
+
when Arel::Nodes::SqlLiteral, Bignum, Fixnum
|
47
|
+
false
|
48
|
+
else
|
49
|
+
true
|
50
|
+
end
|
39
51
|
end
|
40
52
|
|
41
53
|
def visit(object)
|
42
54
|
send(DISPATCH[object.class], object)
|
43
55
|
end
|
44
56
|
|
57
|
+
def visit_Ransack_Nodes_Sort(object)
|
58
|
+
if object.valid?
|
59
|
+
if object.attr.is_a?(Arel::Attributes::Attribute)
|
60
|
+
object.attr.send(object.dir)
|
61
|
+
else
|
62
|
+
ordered(object)
|
63
|
+
end
|
64
|
+
else
|
65
|
+
scope_name = :"sort_by_#{object.name}_#{object.dir}"
|
66
|
+
scope_name if object.context.object.respond_to?(scope_name)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
45
70
|
DISPATCH = Hash.new do |hash, klass|
|
46
71
|
hash[klass] = "visit_#{
|
47
72
|
klass.name.gsub(Constants::TWO_COLONS, Constants::UNDERSCORE)
|
48
73
|
}"
|
49
74
|
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def ordered(object)
|
79
|
+
case object.dir
|
80
|
+
when 'asc'.freeze
|
81
|
+
Arel::Nodes::Ascending.new(object.attr)
|
82
|
+
when 'desc'.freeze
|
83
|
+
Arel::Nodes::Descending.new(object.attr)
|
84
|
+
end
|
85
|
+
end
|
50
86
|
end
|
51
87
|
end
|
data/lib/ransack.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
require 'active_support/core_ext'
|
2
2
|
require 'ransack/configuration'
|
3
|
-
require 'ransack/adapters'
|
4
3
|
require 'polyamorous/polyamorous'
|
5
4
|
|
6
|
-
Ransack::Adapters.object_mapper.require_constants
|
7
|
-
|
8
5
|
module Ransack
|
9
6
|
extend Configuration
|
10
7
|
class UntraversableAssociationError < StandardError; end
|
@@ -12,7 +9,7 @@ end
|
|
12
9
|
|
13
10
|
Ransack.configure do |config|
|
14
11
|
Ransack::Constants::AREL_PREDICATES.each do |name|
|
15
|
-
config.add_predicate name, :
|
12
|
+
config.add_predicate name, arel_predicate: name
|
16
13
|
end
|
17
14
|
Ransack::Constants::DERIVED_PREDICATES.each do |args|
|
18
15
|
config.add_predicate(*args)
|
@@ -22,8 +19,8 @@ end
|
|
22
19
|
require 'ransack/search'
|
23
20
|
require 'ransack/ransacker'
|
24
21
|
require 'ransack/translate'
|
25
|
-
|
26
|
-
|
22
|
+
require 'ransack/active_record'
|
23
|
+
require 'ransack/context'
|
27
24
|
|
28
25
|
ActiveSupport.on_load(:action_controller) do
|
29
26
|
require 'ransack/helpers'
|
@@ -657,6 +657,37 @@ module Ransack
|
|
657
657
|
it { should_not include 'only_sort' }
|
658
658
|
it { should include 'only_admin' }
|
659
659
|
end
|
660
|
+
|
661
|
+
context 'when not defined in model, nor in ApplicationRecord' do
|
662
|
+
subject { Article.ransackable_attributes }
|
663
|
+
|
664
|
+
it "raises a helpful error" do
|
665
|
+
without_application_record_method(:ransackable_attributes) do
|
666
|
+
expect { subject }.to raise_error(RuntimeError, /Ransack needs Article attributes explicitly allowlisted/)
|
667
|
+
end
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
context 'when defined only in model by delegating to super' do
|
672
|
+
subject { Article.ransackable_attributes }
|
673
|
+
|
674
|
+
around do |example|
|
675
|
+
Article.singleton_class.define_method(:ransackable_attributes) do
|
676
|
+
super(nil) - super(nil)
|
677
|
+
end
|
678
|
+
|
679
|
+
example.run
|
680
|
+
ensure
|
681
|
+
Article.singleton_class.remove_method(:ransackable_attributes)
|
682
|
+
end
|
683
|
+
|
684
|
+
it "returns the allowlist in the model, and warns" do
|
685
|
+
without_application_record_method(:ransackable_attributes) do
|
686
|
+
expect { subject }.to output(/Ransack's builtin `ransackable_attributes` method is deprecated/).to_stderr
|
687
|
+
expect(subject).to be_empty
|
688
|
+
end
|
689
|
+
end
|
690
|
+
end
|
660
691
|
end
|
661
692
|
|
662
693
|
describe '#ransortable_attributes' do
|
@@ -689,6 +720,37 @@ module Ransack
|
|
689
720
|
it { should include 'parent' }
|
690
721
|
it { should include 'children' }
|
691
722
|
it { should include 'articles' }
|
723
|
+
|
724
|
+
context 'when not defined in model, nor in ApplicationRecord' do
|
725
|
+
subject { Article.ransackable_associations }
|
726
|
+
|
727
|
+
it "raises a helpful error" do
|
728
|
+
without_application_record_method(:ransackable_associations) do
|
729
|
+
expect { subject }.to raise_error(RuntimeError, /Ransack needs Article associations explicitly allowlisted/)
|
730
|
+
end
|
731
|
+
end
|
732
|
+
end
|
733
|
+
|
734
|
+
context 'when defined only in model by delegating to super' do
|
735
|
+
subject { Article.ransackable_associations }
|
736
|
+
|
737
|
+
around do |example|
|
738
|
+
Article.singleton_class.define_method(:ransackable_associations) do
|
739
|
+
super(nil) - super(nil)
|
740
|
+
end
|
741
|
+
|
742
|
+
example.run
|
743
|
+
ensure
|
744
|
+
Article.singleton_class.remove_method(:ransackable_associations)
|
745
|
+
end
|
746
|
+
|
747
|
+
it "returns the allowlist in the model, and warns" do
|
748
|
+
without_application_record_method(:ransackable_associations) do
|
749
|
+
expect { subject }.to output(/Ransack's builtin `ransackable_associations` method is deprecated/).to_stderr
|
750
|
+
expect(subject).to be_empty
|
751
|
+
end
|
752
|
+
end
|
753
|
+
end
|
692
754
|
end
|
693
755
|
|
694
756
|
describe '#ransackable_scopes' do
|
@@ -704,6 +766,17 @@ module Ransack
|
|
704
766
|
end
|
705
767
|
|
706
768
|
private
|
769
|
+
|
770
|
+
def without_application_record_method(method)
|
771
|
+
ApplicationRecord.singleton_class.alias_method :"original_#{method}", :"#{method}"
|
772
|
+
ApplicationRecord.singleton_class.remove_method :"#{method}"
|
773
|
+
|
774
|
+
yield
|
775
|
+
ensure
|
776
|
+
ApplicationRecord.singleton_class.alias_method :"#{method}", :"original_#{method}"
|
777
|
+
ApplicationRecord.singleton_class.remove_method :"original_#{method}"
|
778
|
+
end
|
779
|
+
|
707
780
|
def rails7_and_mysql
|
708
781
|
::ActiveRecord::VERSION::MAJOR >= 7 && ENV['DB'] == 'mysql'
|
709
782
|
end
|
@@ -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)
|
@@ -138,8 +138,8 @@ module Ransack
|
|
138
138
|
Ransack.configure do |config|
|
139
139
|
config.add_predicate(
|
140
140
|
:test_array_predicate,
|
141
|
-
:
|
142
|
-
:
|
141
|
+
wants_array: true,
|
142
|
+
compounds: true
|
143
143
|
)
|
144
144
|
end
|
145
145
|
|
@@ -153,11 +153,11 @@ module Ransack
|
|
153
153
|
Ransack.configure do |config|
|
154
154
|
config.add_predicate(
|
155
155
|
:test_in_predicate,
|
156
|
-
:
|
156
|
+
arel_predicate: 'in'
|
157
157
|
)
|
158
158
|
config.add_predicate(
|
159
159
|
:test_not_in_predicate,
|
160
|
-
:
|
160
|
+
arel_predicate: 'not_in'
|
161
161
|
)
|
162
162
|
end
|
163
163
|
|
@@ -171,13 +171,13 @@ module Ransack
|
|
171
171
|
Ransack.configure do |config|
|
172
172
|
config.add_predicate(
|
173
173
|
:test_in_predicate_no_array,
|
174
|
-
:
|
175
|
-
:
|
174
|
+
arel_predicate: 'in',
|
175
|
+
wants_array: false
|
176
176
|
)
|
177
177
|
config.add_predicate(
|
178
178
|
:test_not_in_predicate_no_array,
|
179
|
-
:
|
180
|
-
:
|
179
|
+
arel_predicate: 'not_in',
|
180
|
+
wants_array: false
|
181
181
|
)
|
182
182
|
end
|
183
183
|
|
@@ -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
|
@@ -140,6 +140,32 @@ module Ransack
|
|
140
140
|
}
|
141
141
|
end
|
142
142
|
|
143
|
+
describe '#sort_link works even if search params are a string' do
|
144
|
+
before { @controller.view_context.params[:q] = 'input error' }
|
145
|
+
specify {
|
146
|
+
expect { @controller.view_context
|
147
|
+
.sort_link(
|
148
|
+
Person.ransack({}),
|
149
|
+
:name,
|
150
|
+
controller: 'people'
|
151
|
+
)
|
152
|
+
}.not_to raise_error
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
156
|
+
describe '#sort_url works even if search params are a string' do
|
157
|
+
before { @controller.view_context.params[:q] = 'input error' }
|
158
|
+
specify {
|
159
|
+
expect { @controller.view_context
|
160
|
+
.sort_url(
|
161
|
+
Person.ransack({}),
|
162
|
+
:name,
|
163
|
+
controller: 'people'
|
164
|
+
)
|
165
|
+
}.not_to raise_error
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
143
169
|
describe '#sort_link with search_key defined as a string' do
|
144
170
|
subject { @controller.view_context
|
145
171
|
.sort_link(
|
@@ -474,7 +500,7 @@ module Ransack
|
|
474
500
|
describe 'with symbol q:, #sort_link should include search params' do
|
475
501
|
subject { @controller.view_context.sort_link(Person.ransack, :name) }
|
476
502
|
let(:params) { ActionController::Parameters.new(
|
477
|
-
{ :
|
503
|
+
{ q: { name_eq: 'TEST' }, controller: 'people' }
|
478
504
|
) }
|
479
505
|
before { @controller.instance_variable_set(:@params, params) }
|
480
506
|
|
@@ -489,7 +515,7 @@ module Ransack
|
|
489
515
|
describe 'with symbol q:, #sort_url should include search params' do
|
490
516
|
subject { @controller.view_context.sort_url(Person.ransack, :name) }
|
491
517
|
let(:params) { ActionController::Parameters.new(
|
492
|
-
{ :
|
518
|
+
{ q: { name_eq: 'TEST' }, controller: 'people' }
|
493
519
|
) }
|
494
520
|
before { @controller.instance_variable_set(:@params, params) }
|
495
521
|
|
@@ -782,6 +808,14 @@ module Ransack
|
|
782
808
|
it { should_not match /href=".*foo/ }
|
783
809
|
end
|
784
810
|
|
811
|
+
describe "#sort_link ignores host in params" do
|
812
|
+
before { @controller.view_context.params[:host] = 'other_domain' }
|
813
|
+
subject { @controller.view_context.sort_link(Person.ransack, :name, controller: 'people') }
|
814
|
+
|
815
|
+
it { should match /href="\/people\?q/ }
|
816
|
+
it { should_not match /href=".*other_domain/ }
|
817
|
+
end
|
818
|
+
|
785
819
|
describe '#search_form_for with default format' do
|
786
820
|
subject { @controller.view_context
|
787
821
|
.search_form_for(Person.ransack) {} }
|
@@ -74,6 +74,30 @@ module Ransack
|
|
74
74
|
specify { expect(subject).to be_nil }
|
75
75
|
end
|
76
76
|
end
|
77
|
+
|
78
|
+
context 'with an empty predicate' do
|
79
|
+
subject {
|
80
|
+
Condition.extract(
|
81
|
+
Context.for(Person), 'full_name', Person.first.name
|
82
|
+
)
|
83
|
+
}
|
84
|
+
|
85
|
+
context "when default_predicate = nil" do
|
86
|
+
before do
|
87
|
+
Ransack.configure { |c| c.default_predicate = nil }
|
88
|
+
end
|
89
|
+
|
90
|
+
specify { expect(subject).to be_nil }
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when default_predicate = 'eq'" do
|
94
|
+
before do
|
95
|
+
Ransack.configure { |c| c.default_predicate = 'eq' }
|
96
|
+
end
|
97
|
+
|
98
|
+
specify { expect(subject).to eq Condition.extract(Context.for(Person), 'full_name_eq', Person.first.name) }
|
99
|
+
end
|
100
|
+
end
|
77
101
|
end
|
78
102
|
end
|
79
103
|
end
|
@@ -35,6 +35,13 @@ module Ransack
|
|
35
35
|
@s.awesome_eq = nil
|
36
36
|
expect(@s.result.to_sql).not_to match /WHERE/
|
37
37
|
end
|
38
|
+
|
39
|
+
it 'generates a = condition with a huge integer value' do
|
40
|
+
val = 123456789012345678901
|
41
|
+
@s.salary_eq = val
|
42
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
43
|
+
expect(@s.result.to_sql).to match /#{field} = #{val}/
|
44
|
+
end
|
38
45
|
end
|
39
46
|
|
40
47
|
describe 'lteq' do
|
@@ -56,6 +63,13 @@ module Ransack
|
|
56
63
|
@s.salary_lteq = nil
|
57
64
|
expect(@s.result.to_sql).not_to match /WHERE/
|
58
65
|
end
|
66
|
+
|
67
|
+
it 'generates a <= condition with a huge integer value' do
|
68
|
+
val = 123456789012345678901
|
69
|
+
@s.salary_lteq = val
|
70
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
71
|
+
expect(@s.result.to_sql).to match /#{field} <= #{val}/
|
72
|
+
end
|
59
73
|
end
|
60
74
|
|
61
75
|
describe 'lt' do
|
@@ -77,6 +91,13 @@ module Ransack
|
|
77
91
|
@s.salary_lt = nil
|
78
92
|
expect(@s.result.to_sql).not_to match /WHERE/
|
79
93
|
end
|
94
|
+
|
95
|
+
it 'generates a = condition with a huge integer value' do
|
96
|
+
val = 123456789012345678901
|
97
|
+
@s.salary_lt = val
|
98
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
99
|
+
expect(@s.result.to_sql).to match /#{field} < #{val}/
|
100
|
+
end
|
80
101
|
end
|
81
102
|
|
82
103
|
describe 'gteq' do
|
@@ -98,6 +119,13 @@ module Ransack
|
|
98
119
|
@s.salary_gteq = nil
|
99
120
|
expect(@s.result.to_sql).not_to match /WHERE/
|
100
121
|
end
|
122
|
+
|
123
|
+
it 'generates a >= condition with a huge integer value' do
|
124
|
+
val = 123456789012345678901
|
125
|
+
@s.salary_gteq = val
|
126
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
127
|
+
expect(@s.result.to_sql).to match /#{field} >= #{val}/
|
128
|
+
end
|
101
129
|
end
|
102
130
|
|
103
131
|
describe 'gt' do
|
@@ -119,6 +147,13 @@ module Ransack
|
|
119
147
|
@s.salary_gt = nil
|
120
148
|
expect(@s.result.to_sql).not_to match /WHERE/
|
121
149
|
end
|
150
|
+
|
151
|
+
it 'generates a > condition with a huge integer value' do
|
152
|
+
val = 123456789012345678901
|
153
|
+
@s.salary_gt = val
|
154
|
+
field = "#{quote_table_name("people")}.#{quote_column_name("salary")}"
|
155
|
+
expect(@s.result.to_sql).to match /#{field} > #{val}/
|
156
|
+
end
|
122
157
|
end
|
123
158
|
|
124
159
|
describe 'cont' do
|
@@ -368,7 +403,7 @@ module Ransack
|
|
368
403
|
expect(@s.result.to_sql).to match /#{field} IS NULL/
|
369
404
|
end
|
370
405
|
|
371
|
-
describe 'with association
|
406
|
+
describe 'with association query' do
|
372
407
|
it 'generates a value IS NOT NULL query' do
|
373
408
|
@s.comments_id_not_null = true
|
374
409
|
sql = @s.result.to_sql
|
@@ -8,7 +8,7 @@ module Ransack
|
|
8
8
|
ar_translation = ::Namespace::Article.human_attribute_name(:title)
|
9
9
|
ransack_translation = Ransack::Translate.attribute(
|
10
10
|
:title,
|
11
|
-
:
|
11
|
+
context: ::Namespace::Article.ransack.context
|
12
12
|
)
|
13
13
|
expect(ransack_translation).to eq ar_translation
|
14
14
|
end
|
data/spec/support/schema.rb
CHANGED
@@ -28,7 +28,24 @@ else
|
|
28
28
|
)
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
# This is just a test app with no sensitive data, so we explicitly allowlist all
|
32
|
+
# attributes and associations for search. In general, end users should
|
33
|
+
# explicitly authorize each model, but this shows a way to configure the
|
34
|
+
# unrestricted default behavior of versions prior to Ransack 4.
|
35
|
+
#
|
36
|
+
class ApplicationRecord < ActiveRecord::Base
|
37
|
+
self.abstract_class = true
|
38
|
+
|
39
|
+
def self.ransackable_attributes(auth_object = nil)
|
40
|
+
authorizable_ransackable_attributes
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.ransackable_associations(auth_object = nil)
|
44
|
+
authorizable_ransackable_associations
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Person < ApplicationRecord
|
32
49
|
default_scope { order(id: :desc) }
|
33
50
|
belongs_to :parent, class_name: 'Person', foreign_key: :parent_id
|
34
51
|
has_many :children, class_name: 'Person', foreign_key: :parent_id
|
@@ -111,9 +128,9 @@ class Person < ActiveRecord::Base
|
|
111
128
|
|
112
129
|
def self.ransackable_attributes(auth_object = nil)
|
113
130
|
if auth_object == :admin
|
114
|
-
|
131
|
+
authorizable_ransackable_attributes - ['only_sort']
|
115
132
|
else
|
116
|
-
|
133
|
+
authorizable_ransackable_attributes - ['only_sort', 'only_admin']
|
117
134
|
end
|
118
135
|
end
|
119
136
|
|
@@ -129,7 +146,7 @@ end
|
|
129
146
|
class Musician < Person
|
130
147
|
end
|
131
148
|
|
132
|
-
class Article <
|
149
|
+
class Article < ApplicationRecord
|
133
150
|
belongs_to :person
|
134
151
|
has_many :comments
|
135
152
|
has_and_belongs_to_many :tags
|
@@ -182,7 +199,7 @@ end
|
|
182
199
|
class StoryArticle < Article
|
183
200
|
end
|
184
201
|
|
185
|
-
class Recommendation <
|
202
|
+
class Recommendation < ApplicationRecord
|
186
203
|
belongs_to :person
|
187
204
|
belongs_to :target_person, class_name: 'Person'
|
188
205
|
belongs_to :article
|
@@ -200,22 +217,22 @@ module Namespace
|
|
200
217
|
end
|
201
218
|
end
|
202
219
|
|
203
|
-
class Comment <
|
220
|
+
class Comment < ApplicationRecord
|
204
221
|
belongs_to :article
|
205
222
|
belongs_to :person
|
206
223
|
|
207
224
|
default_scope { where(disabled: false) }
|
208
225
|
end
|
209
226
|
|
210
|
-
class Tag <
|
227
|
+
class Tag < ApplicationRecord
|
211
228
|
has_and_belongs_to_many :articles
|
212
229
|
end
|
213
230
|
|
214
|
-
class Note <
|
231
|
+
class Note < ApplicationRecord
|
215
232
|
belongs_to :notable, polymorphic: true
|
216
233
|
end
|
217
234
|
|
218
|
-
class Account <
|
235
|
+
class Account < ApplicationRecord
|
219
236
|
belongs_to :agent_account, class_name: "Account"
|
220
237
|
belongs_to :trade_account, class_name: "Account"
|
221
238
|
end
|
@@ -308,7 +325,7 @@ module Schema
|
|
308
325
|
end
|
309
326
|
|
310
327
|
module SubDB
|
311
|
-
class Base <
|
328
|
+
class Base < ApplicationRecord
|
312
329
|
self.abstract_class = true
|
313
330
|
establish_connection(
|
314
331
|
adapter: 'sqlite3',
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ransack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ernie Miller
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2023-02-09 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activerecord
|
@@ -69,6 +69,7 @@ extra_rdoc_files: []
|
|
69
69
|
files:
|
70
70
|
- ".github/FUNDING.yml"
|
71
71
|
- ".github/SECURITY.md"
|
72
|
+
- ".github/workflows/codeql.yml"
|
72
73
|
- ".github/workflows/cronjob.yml"
|
73
74
|
- ".github/workflows/deploy.yml"
|
74
75
|
- ".github/workflows/rubocop.yml"
|
@@ -139,7 +140,6 @@ files:
|
|
139
140
|
- docs/static/logo/ransack.png
|
140
141
|
- docs/static/logo/ransack.svg
|
141
142
|
- docs/yarn.lock
|
142
|
-
- lib/polyamorous.rb
|
143
143
|
- lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb
|
144
144
|
- lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb
|
145
145
|
- lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb
|
@@ -154,15 +154,9 @@ files:
|
|
154
154
|
- lib/polyamorous/swapping_reflection_class.rb
|
155
155
|
- lib/polyamorous/tree_node.rb
|
156
156
|
- lib/ransack.rb
|
157
|
-
- lib/ransack/
|
158
|
-
- lib/ransack/adapters/active_record.rb
|
157
|
+
- lib/ransack/active_record.rb
|
159
158
|
- lib/ransack/adapters/active_record/base.rb
|
160
159
|
- lib/ransack/adapters/active_record/context.rb
|
161
|
-
- lib/ransack/adapters/active_record/ransack/constants.rb
|
162
|
-
- lib/ransack/adapters/active_record/ransack/context.rb
|
163
|
-
- lib/ransack/adapters/active_record/ransack/nodes/condition.rb
|
164
|
-
- lib/ransack/adapters/active_record/ransack/translate.rb
|
165
|
-
- lib/ransack/adapters/active_record/ransack/visitor.rb
|
166
160
|
- lib/ransack/configuration.rb
|
167
161
|
- lib/ransack/constants.rb
|
168
162
|
- lib/ransack/context.rb
|
@@ -196,7 +190,6 @@ files:
|
|
196
190
|
- lib/ransack/locale/zh-CN.yml
|
197
191
|
- lib/ransack/locale/zh-TW.yml
|
198
192
|
- lib/ransack/naming.rb
|
199
|
-
- lib/ransack/nodes.rb
|
200
193
|
- lib/ransack/nodes/attribute.rb
|
201
194
|
- lib/ransack/nodes/bindable.rb
|
202
195
|
- lib/ransack/nodes/condition.rb
|
@@ -256,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
256
249
|
- !ruby/object:Gem::Version
|
257
250
|
version: '0'
|
258
251
|
requirements: []
|
259
|
-
rubygems_version: 3.
|
252
|
+
rubygems_version: 3.4.6
|
260
253
|
signing_key:
|
261
254
|
specification_version: 4
|
262
255
|
summary: Object-based searching for Active Record.
|
data/lib/polyamorous.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'polyamorous/polyamorous'
|