ransack 3.0.0 → 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/deploy.yml +35 -0
- data/.github/workflows/test-deploy.yml +29 -0
- data/.github/workflows/test.yml +22 -39
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +118 -0
- data/CONTRIBUTING.md +38 -16
- data/Gemfile +10 -10
- data/README.md +9 -14
- data/bug_report_templates/test-ransacker-arel-present-predicate.rb +4 -0
- data/docs/.gitignore +0 -1
- 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 +30 -26
- data/docs/docs/getting-started/sorting.md +1 -1
- data/docs/docs/getting-started/using-predicates.md +1 -1
- data/docs/docs/going-further/acts-as-taggable-on.md +114 -0
- data/docs/docs/going-further/documentation.md +14 -2
- data/docs/docs/going-further/exporting-to-csv.md +2 -2
- data/docs/docs/going-further/form-customisation.md +1 -1
- data/docs/docs/going-further/i18n.md +3 -3
- data/docs/docs/going-further/merging-searches.md +1 -1
- data/docs/docs/going-further/other-notes.md +1 -1
- data/docs/docs/going-further/polymorphic-search.md +40 -0
- data/docs/docs/going-further/saving-queries.md +1 -1
- data/docs/docs/going-further/searching-postgres.md +1 -1
- data/docs/docs/going-further/wiki-contributors.md +82 -0
- data/docs/docs/intro.md +2 -2
- data/docs/docusaurus.config.js +16 -4
- data/docs/package.json +7 -2
- data/docs/yarn.lock +3036 -1917
- data/lib/polyamorous/activerecord_6.1_ruby_2/reflection.rb +11 -1
- 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/ransack/adapters/active_record/base.rb +78 -7
- data/lib/ransack/adapters/active_record/context.rb +17 -49
- data/lib/ransack/configuration.rb +25 -12
- data/lib/ransack/constants.rb +125 -3
- data/lib/ransack/context.rb +34 -5
- data/lib/ransack/helpers/form_builder.rb +3 -3
- data/lib/ransack/helpers/form_helper.rb +4 -3
- 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 +2 -2
- 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/ransack.gemspec +3 -3
- data/spec/helpers/polyamorous_helper.rb +2 -8
- 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 +60 -2
- data/spec/ransack/nodes/condition_spec.rb +24 -0
- data/spec/ransack/nodes/value_spec.rb +115 -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 +20 -21
- data/docs/package-lock.json +0 -9207
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +0 -20
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +0 -79
- data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +0 -11
- 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 -69
- 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/{adapters/active_record.rb → active_record.rb} +0 -0
@@ -7,9 +7,9 @@ module Ransack
|
|
7
7
|
alias :m= :combinator=
|
8
8
|
|
9
9
|
i18n_word :condition, :and, :or
|
10
|
-
i18n_alias :
|
10
|
+
i18n_alias c: :condition, n: :and, o: :or
|
11
11
|
|
12
|
-
delegate :each, :
|
12
|
+
delegate :each, to: :values
|
13
13
|
|
14
14
|
def initialize(context, combinator = nil)
|
15
15
|
super(context)
|
@@ -22,7 +22,7 @@ module Ransack
|
|
22
22
|
|
23
23
|
def translate(key, options = {})
|
24
24
|
super or Translate.attribute(
|
25
|
-
key.to_s, options.merge(:
|
25
|
+
key.to_s, options.merge(context: context)
|
26
26
|
)
|
27
27
|
end
|
28
28
|
|
data/lib/ransack/nodes/node.rb
CHANGED
data/lib/ransack/nodes/value.rb
CHANGED
@@ -2,7 +2,7 @@ module Ransack
|
|
2
2
|
module Nodes
|
3
3
|
class Value < Node
|
4
4
|
attr_accessor :value
|
5
|
-
delegate :present?, :blank?, :
|
5
|
+
delegate :present?, :blank?, to: :value
|
6
6
|
|
7
7
|
def initialize(context, value = nil)
|
8
8
|
super(context)
|
@@ -26,7 +26,7 @@ module Ransack
|
|
26
26
|
case type
|
27
27
|
when :date
|
28
28
|
cast_to_date(value)
|
29
|
-
when :datetime, :timestamp, :time
|
29
|
+
when :datetime, :timestamp, :time, :timestamptz
|
30
30
|
cast_to_time(value)
|
31
31
|
when :boolean
|
32
32
|
cast_to_boolean(value)
|
data/lib/ransack/predicate.rb
CHANGED
data/lib/ransack/ransacker.rb
CHANGED
data/lib/ransack/search.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
-
require 'ransack/nodes'
|
1
|
+
require 'ransack/nodes/bindable'
|
2
|
+
require 'ransack/nodes/node'
|
3
|
+
require 'ransack/nodes/attribute'
|
4
|
+
require 'ransack/nodes/value'
|
5
|
+
require 'ransack/nodes/condition'
|
6
|
+
require 'ransack/nodes/sort'
|
7
|
+
require 'ransack/nodes/grouping'
|
2
8
|
require 'ransack/context'
|
3
|
-
Ransack::Adapters.object_mapper.require_search
|
4
9
|
require 'ransack/naming'
|
5
10
|
|
6
11
|
module Ransack
|
@@ -9,10 +14,10 @@ module Ransack
|
|
9
14
|
|
10
15
|
attr_reader :base, :context
|
11
16
|
|
12
|
-
delegate :object, :klass, :
|
17
|
+
delegate :object, :klass, to: :context
|
13
18
|
delegate :new_grouping, :new_condition,
|
14
19
|
:build_grouping, :build_condition,
|
15
|
-
:translate, :
|
20
|
+
:translate, to: :base
|
16
21
|
|
17
22
|
def initialize(object, params = {}, options = {})
|
18
23
|
strip_whitespace = options.fetch(:strip_whitespace, Ransack.options[:strip_whitespace])
|
data/lib/ransack/translate.rb
CHANGED
@@ -66,7 +66,7 @@ module Ransack
|
|
66
66
|
[:"ransack.associations.#{i18n_key(context.klass)}.#{key}"]
|
67
67
|
end
|
68
68
|
defaults << context.traverse(key).model_name.human
|
69
|
-
options = { :
|
69
|
+
options = { count: 1, default: defaults }
|
70
70
|
I18n.translate(defaults.shift, **options)
|
71
71
|
end
|
72
72
|
|
@@ -149,7 +149,7 @@ module Ransack
|
|
149
149
|
end
|
150
150
|
|
151
151
|
def i18n_key(klass)
|
152
|
-
|
152
|
+
klass.model_name.i18n_key
|
153
153
|
end
|
154
154
|
end
|
155
155
|
end
|
data/lib/ransack/version.rb
CHANGED
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'
|
data/ransack.gemspec
CHANGED
@@ -12,11 +12,11 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.homepage = "https://github.com/activerecord-hackery/ransack"
|
13
13
|
s.summary = %q{Object-based searching for Active Record.}
|
14
14
|
s.description = %q{Ransack is the successor to the MetaSearch gem. It improves and expands upon MetaSearch's functionality, but does not have a 100%-compatible API.}
|
15
|
-
s.required_ruby_version = '>= 2.
|
15
|
+
s.required_ruby_version = '>= 2.7'
|
16
16
|
s.license = 'MIT'
|
17
17
|
|
18
|
-
s.add_dependency 'activerecord', '>= 6.
|
19
|
-
s.add_dependency 'activesupport', '>= 6.
|
18
|
+
s.add_dependency 'activerecord', '>= 6.1.5'
|
19
|
+
s.add_dependency 'activesupport', '>= 6.1.5'
|
20
20
|
s.add_dependency 'i18n'
|
21
21
|
|
22
22
|
s.files = `git ls-files`.split("\n")
|
@@ -3,14 +3,8 @@ module PolyamorousHelper
|
|
3
3
|
Polyamorous::JoinAssociation.new reflection, children, klass
|
4
4
|
end
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
Polyamorous::JoinDependency.new klass, klass.arel_table, associations, Polyamorous::InnerJoin
|
9
|
-
end
|
10
|
-
else
|
11
|
-
def new_join_dependency(klass, associations = {})
|
12
|
-
Polyamorous::JoinDependency.new klass, klass.arel_table, associations
|
13
|
-
end
|
6
|
+
def new_join_dependency(klass, associations = {})
|
7
|
+
Polyamorous::JoinDependency.new klass, klass.arel_table, associations, Polyamorous::InnerJoin
|
14
8
|
end
|
15
9
|
|
16
10
|
def new_join(name, type = Polyamorous::InnerJoin, klass = nil)
|
@@ -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
|
|
@@ -758,6 +784,38 @@ module Ransack
|
|
758
784
|
end
|
759
785
|
end
|
760
786
|
|
787
|
+
describe '#sort_link with data option' do
|
788
|
+
subject { @controller.view_context
|
789
|
+
.sort_link(
|
790
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
791
|
+
:name,
|
792
|
+
data: { turbo_action: :advance }, controller: 'people'
|
793
|
+
)
|
794
|
+
}
|
795
|
+
it { should match /data-turbo-action="advance"/ }
|
796
|
+
it { should_not match /people\?data%5Bturbo_action%5D=advance/ }
|
797
|
+
end
|
798
|
+
|
799
|
+
describe "#sort_link with host option" do
|
800
|
+
subject { @controller.view_context
|
801
|
+
.sort_link(
|
802
|
+
[:main_app, Person.ransack(sorts: ['name desc'])],
|
803
|
+
:name,
|
804
|
+
host: 'foo', controller: 'people'
|
805
|
+
)
|
806
|
+
}
|
807
|
+
it { should match /href="\/people\?q/ }
|
808
|
+
it { should_not match /href=".*foo/ }
|
809
|
+
end
|
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
|
+
|
761
819
|
describe '#search_form_for with default format' do
|
762
820
|
subject { @controller.view_context
|
763
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
|