ransack 1.6.6 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/.travis.yml +35 -53
- data/CHANGELOG.md +530 -9
- data/CONTRIBUTING.md +63 -26
- data/Gemfile +24 -24
- data/README.md +371 -96
- data/Rakefile +6 -29
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_association.rb +24 -0
- data/lib/polyamorous/activerecord_5.2_ruby_2/join_dependency.rb +79 -0
- data/lib/polyamorous/activerecord_5.2_ruby_2/reflection.rb +11 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_association.rb +1 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/join_dependency.rb +80 -0
- data/lib/polyamorous/activerecord_6.0_ruby_2/reflection.rb +1 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_association.rb +74 -0
- data/lib/polyamorous/activerecord_6.1_ruby_2/join_dependency.rb +93 -0
- data/lib/polyamorous/activerecord_6.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/ransack/adapters/active_record/base.rb +23 -2
- data/lib/ransack/adapters/active_record/context.rb +206 -139
- data/lib/ransack/adapters/active_record/ransack/constants.rb +70 -55
- data/lib/ransack/adapters/active_record/ransack/context.rb +10 -18
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +43 -36
- 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 +11 -10
- data/lib/ransack/adapters.rb +64 -0
- data/lib/ransack/configuration.rb +91 -4
- data/lib/ransack/constants.rb +13 -26
- data/lib/ransack/context.rb +45 -40
- data/lib/ransack/helpers/form_builder.rb +21 -12
- data/lib/ransack/helpers/form_helper.rb +99 -69
- 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/da.yml +70 -0
- data/lib/ransack/locale/de.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/id.yml +70 -0
- data/lib/ransack/locale/it.yml +70 -0
- data/lib/ransack/locale/ja.yml +70 -0
- data/lib/ransack/locale/nl.yml +4 -4
- data/lib/ransack/locale/pt-BR.yml +70 -0
- data/lib/ransack/locale/ru.yml +70 -0
- data/lib/ransack/locale/sk.yml +70 -0
- data/lib/ransack/locale/tr.yml +70 -0
- data/lib/ransack/locale/{zh.yml → zh-CN.yml} +13 -13
- data/lib/ransack/locale/zh-TW.yml +70 -0
- data/lib/ransack/nodes/attribute.rb +6 -3
- data/lib/ransack/nodes/bindable.rb +18 -6
- data/lib/ransack/nodes/condition.rb +85 -24
- data/lib/ransack/nodes/grouping.rb +17 -11
- data/lib/ransack/nodes/sort.rb +9 -5
- data/lib/ransack/nodes/value.rb +74 -68
- data/lib/ransack/nodes.rb +2 -3
- data/lib/ransack/predicate.rb +17 -20
- data/lib/ransack/search.rb +15 -15
- 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 +11 -17
- data/logo/ransack-h.png +0 -0
- data/logo/ransack-h.svg +34 -0
- data/logo/ransack-v.png +0 -0
- data/logo/ransack-v.svg +34 -0
- data/logo/ransack.png +0 -0
- data/logo/ransack.svg +21 -0
- data/ransack.gemspec +9 -27
- data/spec/console.rb +4 -0
- data/spec/helpers/polyamorous_helper.rb +19 -0
- data/spec/polyamorous/join_association_spec.rb +35 -0
- data/spec/polyamorous/join_dependency_spec.rb +97 -0
- data/spec/polyamorous/join_spec.rb +19 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +380 -91
- data/spec/ransack/adapters/active_record/context_spec.rb +72 -33
- data/spec/ransack/configuration_spec.rb +87 -14
- data/spec/ransack/helpers/form_builder_spec.rb +2 -11
- data/spec/ransack/helpers/form_helper_spec.rb +481 -113
- data/spec/ransack/nodes/condition_spec.rb +25 -1
- data/spec/ransack/nodes/grouping_spec.rb +62 -6
- data/spec/ransack/predicate_spec.rb +79 -5
- data/spec/ransack/search_spec.rb +159 -79
- data/spec/spec_helper.rb +8 -0
- data/spec/support/schema.rb +99 -37
- metadata +57 -184
- data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
- data/lib/ransack/adapters/active_record/3.0/context.rb +0 -205
- data/lib/ransack/adapters/active_record/3.1/context.rb +0 -219
- 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/3.2/.gitkeep +0 -0
- 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 -126
- data/lib/ransack/adapters/mongoid/context.rb +0 -208
- 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 -13
- data/spec/mongoid/adapters/mongoid/base_spec.rb +0 -276
- data/spec/mongoid/adapters/mongoid/context_spec.rb +0 -56
- data/spec/mongoid/configuration_spec.rb +0 -102
- 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 -34
- data/spec/mongoid/nodes/grouping_spec.rb +0 -13
- data/spec/mongoid/predicate_spec.rb +0 -155
- data/spec/mongoid/search_spec.rb +0 -446
- data/spec/mongoid/support/mongoid.yml +0 -6
- data/spec/mongoid/support/schema.rb +0 -128
- data/spec/mongoid/translate_spec.rb +0 -14
- data/spec/mongoid_spec_helper.rb +0 -59
- data/spec/ransack/dependencies_spec.rb +0 -10
@@ -3,56 +3,63 @@ module Ransack
|
|
3
3
|
class Condition
|
4
4
|
|
5
5
|
def arel_predicate
|
6
|
-
|
6
|
+
attributes.map { |attribute|
|
7
|
+
association = attribute.parent
|
8
|
+
if negative? && attribute.associated_collection?
|
9
|
+
query = context.build_correlated_subquery(association)
|
10
|
+
context.remove_association(association)
|
11
|
+
if self.predicate_name == 'not_null' && self.value
|
12
|
+
query.where(format_predicate(attribute))
|
13
|
+
Arel::Nodes::In.new(context.primary_key, Arel.sql(query.to_sql))
|
14
|
+
else
|
15
|
+
query.where(format_predicate(attribute).not)
|
16
|
+
Arel::Nodes::NotIn.new(context.primary_key, Arel.sql(query.to_sql))
|
17
|
+
end
|
18
|
+
else
|
19
|
+
format_predicate(attribute)
|
20
|
+
end
|
21
|
+
}.reduce(combinator_method)
|
7
22
|
end
|
8
23
|
|
9
24
|
private
|
10
25
|
|
11
|
-
def
|
12
|
-
|
13
|
-
a.attr.send(
|
14
|
-
arel_predicate_for_attribute(a), formatted_values_for_attribute(a)
|
15
|
-
)
|
16
|
-
end
|
26
|
+
def combinator_method
|
27
|
+
combinator === Constants::OR ? :or : :and
|
17
28
|
end
|
18
29
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
format_predicate(predicates.first)
|
24
|
-
end
|
25
|
-
end
|
30
|
+
def format_predicate(attribute)
|
31
|
+
arel_pred = arel_predicate_for_attribute(attribute)
|
32
|
+
arel_values = formatted_values_for_attribute(attribute)
|
33
|
+
predicate = attr_value_for_attribute(attribute).public_send(arel_pred, arel_values)
|
26
34
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
elsif combinator === Constants::OR
|
31
|
-
predicates.inject(&:or)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def format_predicate(predicate)
|
36
|
-
predicate.tap do
|
37
|
-
if casted_array_with_in_predicate?(predicate)
|
38
|
-
predicate.right[0] = predicate.right[0].val.map { |v| format(v) }
|
35
|
+
if in_predicate?(predicate)
|
36
|
+
predicate.right = predicate.right.map do |pr|
|
37
|
+
casted_array?(pr) ? format_values_for(pr) : pr
|
39
38
|
end
|
40
39
|
end
|
40
|
+
|
41
|
+
predicate
|
41
42
|
end
|
42
43
|
|
43
|
-
def
|
44
|
+
def in_predicate?(predicate)
|
44
45
|
return unless defined?(Arel::Nodes::Casted)
|
45
|
-
predicate.class == Arel::Nodes::In
|
46
|
-
predicate.right[0].respond_to?(:val) &&
|
47
|
-
predicate.right[0].val.is_a?(Array)
|
46
|
+
predicate.class == Arel::Nodes::In || predicate.class == Arel::Nodes::NotIn
|
48
47
|
end
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
def casted_array?(predicate)
|
50
|
+
(predicate.respond_to?(:value) && predicate.value.is_a?(Array)) || # Rails 6.1
|
51
|
+
(predicate.respond_to?(:val) && predicate.val.is_a?(Array)) # Rails 5.2, 6.0
|
52
|
+
end
|
53
|
+
|
54
|
+
def format_values_for(predicate)
|
55
|
+
value = if predicate.respond_to?(:value)
|
56
|
+
predicate.value # Rails 6.1
|
57
|
+
else
|
58
|
+
predicate.val # Rails 5.2, 6.0
|
59
|
+
end
|
60
|
+
|
61
|
+
value.map do |val|
|
62
|
+
val.is_a?(String) ? Arel::Nodes.build_quoted(val) : val
|
56
63
|
end
|
57
64
|
end
|
58
65
|
|
@@ -2,11 +2,7 @@ module Ransack
|
|
2
2
|
module Translate
|
3
3
|
|
4
4
|
def self.i18n_key(klass)
|
5
|
-
|
6
|
-
klass.model_name.i18n_key.to_s.tr('.'.freeze, '/'.freeze)
|
7
|
-
else
|
8
|
-
klass.model_name.i18n_key.to_s.freeze
|
9
|
-
end
|
5
|
+
klass.model_name.i18n_key
|
10
6
|
end
|
11
7
|
end
|
12
8
|
end
|
@@ -20,5 +20,28 @@ module Ransack
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
def visit_Ransack_Nodes_Sort(object)
|
24
|
+
if object.valid?
|
25
|
+
if object.attr.is_a?(Arel::Attributes::Attribute)
|
26
|
+
object.attr.send(object.dir)
|
27
|
+
else
|
28
|
+
ordered(object)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
scope_name = :"sort_by_#{object.name}_#{object.dir}"
|
32
|
+
scope_name if object.context.object.respond_to?(scope_name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def ordered(object)
|
39
|
+
case object.dir
|
40
|
+
when 'asc'.freeze
|
41
|
+
Arel::Nodes::Ascending.new(object.attr)
|
42
|
+
when 'desc'.freeze
|
43
|
+
Arel::Nodes::Descending.new(object.attr)
|
44
|
+
end
|
45
|
+
end
|
23
46
|
end
|
24
47
|
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
require 'ransack/adapters/active_record/base'
|
2
|
-
ActiveRecord::Base.extend Ransack::Adapters::ActiveRecord::Base
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
ActiveSupport.on_load(:active_record) do
|
4
|
+
extend Ransack::Adapters::ActiveRecord::Base
|
5
|
+
|
6
|
+
Ransack::SUPPORTS_ATTRIBUTE_ALIAS =
|
7
|
+
begin
|
8
|
+
ActiveRecord::Base.respond_to?(:attribute_aliases)
|
9
|
+
rescue NameError
|
10
|
+
false
|
11
|
+
end
|
13
12
|
end
|
13
|
+
|
14
|
+
require 'ransack/adapters/active_record/context'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Ransack
|
2
|
+
module Adapters
|
3
|
+
|
4
|
+
def self.object_mapper
|
5
|
+
@object_mapper ||= instantiate_object_mapper
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.instantiate_object_mapper
|
9
|
+
if defined?(::ActiveRecord::Base)
|
10
|
+
ActiveRecordAdapter.new
|
11
|
+
elsif defined?(::Mongoid)
|
12
|
+
MongoidAdapter.new
|
13
|
+
else
|
14
|
+
raise "Unsupported adapter"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ActiveRecordAdapter
|
19
|
+
def require_constants
|
20
|
+
require 'ransack/adapters/active_record/ransack/constants'
|
21
|
+
end
|
22
|
+
|
23
|
+
def require_adapter
|
24
|
+
require 'ransack/adapters/active_record/ransack/translate'
|
25
|
+
require 'ransack/adapters/active_record'
|
26
|
+
end
|
27
|
+
|
28
|
+
def require_context
|
29
|
+
require 'ransack/adapters/active_record/ransack/visitor'
|
30
|
+
end
|
31
|
+
|
32
|
+
def require_nodes
|
33
|
+
require 'ransack/adapters/active_record/ransack/nodes/condition'
|
34
|
+
end
|
35
|
+
|
36
|
+
def require_search
|
37
|
+
require 'ransack/adapters/active_record/ransack/context'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class MongoidAdapter
|
42
|
+
def require_constants
|
43
|
+
require 'ransack/adapters/mongoid/ransack/constants'
|
44
|
+
end
|
45
|
+
|
46
|
+
def require_adapter
|
47
|
+
require 'ransack/adapters/mongoid/ransack/translate'
|
48
|
+
require 'ransack/adapters/mongoid'
|
49
|
+
end
|
50
|
+
|
51
|
+
def require_context
|
52
|
+
require 'ransack/adapters/mongoid/ransack/visitor'
|
53
|
+
end
|
54
|
+
|
55
|
+
def require_nodes
|
56
|
+
require 'ransack/adapters/mongoid/ransack/nodes/condition'
|
57
|
+
end
|
58
|
+
|
59
|
+
def require_search
|
60
|
+
require 'ransack/adapters/mongoid/ransack/context'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -5,10 +5,35 @@ module Ransack
|
|
5
5
|
module Configuration
|
6
6
|
|
7
7
|
mattr_accessor :predicates, :options
|
8
|
-
|
8
|
+
|
9
|
+
class PredicateCollection
|
10
|
+
attr_reader :sorted_names_with_underscores
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@collection = {}
|
14
|
+
@sorted_names_with_underscores = []
|
15
|
+
end
|
16
|
+
|
17
|
+
delegate :[], :keys, :has_key?, to: :@collection
|
18
|
+
|
19
|
+
def []=(key, value)
|
20
|
+
@sorted_names_with_underscores << [key, '_' + key]
|
21
|
+
@sorted_names_with_underscores.sort! { |(a, _), (b, _)| b.length <=> a.length }
|
22
|
+
|
23
|
+
@collection[key] = value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
self.predicates = PredicateCollection.new
|
28
|
+
|
9
29
|
self.options = {
|
10
30
|
:search_key => :q,
|
11
|
-
:ignore_unknown_conditions => true
|
31
|
+
:ignore_unknown_conditions => true,
|
32
|
+
:hide_sort_order_indicators => false,
|
33
|
+
:up_arrow => '▼'.freeze,
|
34
|
+
:down_arrow => '▲'.freeze,
|
35
|
+
:default_arrow => nil,
|
36
|
+
:sanitize_scope_args => true
|
12
37
|
}
|
13
38
|
|
14
39
|
def configure
|
@@ -61,12 +86,74 @@ module Ransack
|
|
61
86
|
self.options[:search_key] = name
|
62
87
|
end
|
63
88
|
|
64
|
-
#
|
65
|
-
# into a search.
|
89
|
+
# By default Ransack ignores errors if an unknown predicate, condition or
|
90
|
+
# attribute is passed into a search. The default may be overridden in an
|
91
|
+
# initializer file like `config/initializers/ransack.rb` as follows:
|
92
|
+
#
|
93
|
+
# Ransack.configure do |config|
|
94
|
+
# # Raise if an unknown predicate, condition or attribute is passed
|
95
|
+
# config.ignore_unknown_conditions = false
|
96
|
+
# end
|
97
|
+
#
|
66
98
|
def ignore_unknown_conditions=(boolean)
|
67
99
|
self.options[:ignore_unknown_conditions] = boolean
|
68
100
|
end
|
69
101
|
|
102
|
+
# By default, Ransack displays sort order indicator arrows with HTML codes:
|
103
|
+
#
|
104
|
+
# up_arrow: '▼'
|
105
|
+
# down_arrow: '▲'
|
106
|
+
#
|
107
|
+
# There is also a default arrow which is displayed if a column is not sorted.
|
108
|
+
# By default this is nil so nothing will be displayed.
|
109
|
+
#
|
110
|
+
# Any of the defaults may be globally overridden in an initializer file
|
111
|
+
# like `config/initializers/ransack.rb` as follows:
|
112
|
+
#
|
113
|
+
# Ransack.configure do |config|
|
114
|
+
# # Globally set the up arrow to an icon, and the down and default arrows to unicode.
|
115
|
+
# config.custom_arrows = {
|
116
|
+
# up_arrow: '<i class="fa fa-long-arrow-up"></i>',
|
117
|
+
# down_arrow: 'U+02193',
|
118
|
+
# default_arrow: 'U+11047'
|
119
|
+
# }
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
def custom_arrows=(opts = {})
|
123
|
+
self.options[:up_arrow] = opts[:up_arrow].freeze if opts[:up_arrow]
|
124
|
+
self.options[:down_arrow] = opts[:down_arrow].freeze if opts[:down_arrow]
|
125
|
+
self.options[:default_arrow] = opts[:default_arrow].freeze if opts[:default_arrow]
|
126
|
+
end
|
127
|
+
|
128
|
+
# Ransack sanitizes many values in your custom scopes into booleans.
|
129
|
+
# [1, '1', 't', 'T', 'true', 'TRUE'] all evaluate to true.
|
130
|
+
# [0, '0', 'f', 'F', 'false', 'FALSE'] all evaluate to false.
|
131
|
+
#
|
132
|
+
# This default may be globally overridden in an initializer file like
|
133
|
+
# `config/initializers/ransack.rb` as follows:
|
134
|
+
#
|
135
|
+
# Ransack.configure do |config|
|
136
|
+
# # Accept my custom scope values as what they are.
|
137
|
+
# config.sanitize_custom_scope_booleans = false
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
def sanitize_custom_scope_booleans=(boolean)
|
141
|
+
self.options[:sanitize_scope_args] = boolean
|
142
|
+
end
|
143
|
+
|
144
|
+
# By default, Ransack displays sort order indicator arrows in sort links.
|
145
|
+
# The default may be globally overridden in an initializer file like
|
146
|
+
# `config/initializers/ransack.rb` as follows:
|
147
|
+
#
|
148
|
+
# Ransack.configure do |config|
|
149
|
+
# # Hide sort link order indicators globally across the application
|
150
|
+
# config.hide_sort_order_indicators = true
|
151
|
+
# end
|
152
|
+
#
|
153
|
+
def hide_sort_order_indicators=(boolean)
|
154
|
+
self.options[:hide_sort_order_indicators] = boolean
|
155
|
+
end
|
156
|
+
|
70
157
|
def arel_predicate_with_suffix(arel_predicate, suffix)
|
71
158
|
if arel_predicate === Proc
|
72
159
|
proc { |v| "#{arel_predicate.call(v)}#{suffix}" }
|
data/lib/ransack/constants.rb
CHANGED
@@ -1,19 +1,7 @@
|
|
1
1
|
module Ransack
|
2
2
|
module Constants
|
3
|
-
ASC = 'asc'.freeze
|
4
|
-
DESC = 'desc'.freeze
|
5
|
-
ASC_DESC = [ASC, DESC].freeze
|
6
|
-
|
7
|
-
ASC_ARROW = '▲'.freeze
|
8
|
-
DESC_ARROW = '▼'.freeze
|
9
|
-
|
10
3
|
OR = 'or'.freeze
|
11
4
|
AND = 'and'.freeze
|
12
|
-
SPACED_AND = ' AND '.freeze
|
13
|
-
|
14
|
-
SORT = 'sort'.freeze
|
15
|
-
SORT_LINK = 'sort_link'.freeze
|
16
|
-
SORT_DIRECTION = 'sort_direction'.freeze
|
17
5
|
|
18
6
|
CAP_SEARCH = 'Search'.freeze
|
19
7
|
SEARCH = 'search'.freeze
|
@@ -23,17 +11,12 @@ module Ransack
|
|
23
11
|
ATTRIBUTES = 'attributes'.freeze
|
24
12
|
COMBINATOR = 'combinator'.freeze
|
25
13
|
|
26
|
-
SPACE = ' '.freeze
|
27
|
-
COMMA_SPACE = ', '.freeze
|
28
|
-
COLON_SPACE = ': '.freeze
|
29
14
|
TWO_COLONS = '::'.freeze
|
30
15
|
UNDERSCORE = '_'.freeze
|
31
16
|
LEFT_PARENTHESIS = '('.freeze
|
32
17
|
Q = 'q'.freeze
|
33
18
|
I = 'i'.freeze
|
34
|
-
NON_BREAKING_SPACE = ' '.freeze
|
35
19
|
DOT_ASTERIX = '.*'.freeze
|
36
|
-
EMPTY = ''.freeze
|
37
20
|
|
38
21
|
STRING_JOIN = 'string_join'.freeze
|
39
22
|
ASSOCIATION_JOIN = 'association_join'.freeze
|
@@ -44,14 +27,17 @@ module Ransack
|
|
44
27
|
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
|
45
28
|
BOOLEAN_VALUES = (TRUE_VALUES + FALSE_VALUES).freeze
|
46
29
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
30
|
+
AND_OR = ['and'.freeze, 'or'.freeze].freeze
|
31
|
+
IN_NOT_IN = ['in'.freeze, 'not_in'.freeze].freeze
|
32
|
+
SUFFIXES = ['_any'.freeze, '_all'.freeze].freeze
|
33
|
+
AREL_PREDICATES = [
|
34
|
+
'eq'.freeze, 'not_eq'.freeze,
|
35
|
+
'matches'.freeze, 'does_not_match'.freeze,
|
36
|
+
'lt'.freeze, 'lteq'.freeze,
|
37
|
+
'gt'.freeze, 'gteq'.freeze,
|
38
|
+
'in'.freeze, 'not_in'.freeze
|
39
|
+
].freeze
|
40
|
+
A_S_I = ['a'.freeze, 's'.freeze, 'i'.freeze].freeze
|
55
41
|
|
56
42
|
EQ = 'eq'.freeze
|
57
43
|
NOT_EQ = 'not_eq'.freeze
|
@@ -59,7 +45,8 @@ module Ransack
|
|
59
45
|
NOT_EQ_ALL = 'not_eq_all'.freeze
|
60
46
|
CONT = 'cont'.freeze
|
61
47
|
|
62
|
-
|
48
|
+
RAILS_6_0 = '6.0.0'.freeze
|
49
|
+
RAILS_6_1_ALPHA = '6.1.0.alpha'.freeze
|
63
50
|
|
64
51
|
RANSACK_SLASH_SEARCHES = 'ransack/searches'.freeze
|
65
52
|
RANSACK_SLASH_SEARCHES_SLASH_SEARCH = 'ransack/searches/search'.freeze
|
data/lib/ransack/context.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
1
|
require 'ransack/visitor'
|
2
|
-
|
3
|
-
if defined?(::ActiveRecord::Base)
|
4
|
-
require 'ransack/adapters/active_record/ransack/visitor'
|
5
|
-
end
|
6
|
-
|
7
|
-
if defined?(::Mongoid)
|
8
|
-
require 'ransack/adapters/mongoid/ransack/visitor'
|
9
|
-
end
|
2
|
+
Ransack::Adapters.object_mapper.require_context
|
10
3
|
|
11
4
|
module Ransack
|
12
5
|
class Context
|
@@ -24,9 +17,12 @@ module Ransack
|
|
24
17
|
end
|
25
18
|
|
26
19
|
def for(object, options = {})
|
27
|
-
context =
|
28
|
-
|
29
|
-
|
20
|
+
context =
|
21
|
+
if Class === object
|
22
|
+
for_class(object, options)
|
23
|
+
else
|
24
|
+
for_object(object, options)
|
25
|
+
end
|
30
26
|
context or raise ArgumentError,
|
31
27
|
"Don't know what context to use for #{object}"
|
32
28
|
end
|
@@ -44,7 +40,7 @@ module Ransack
|
|
44
40
|
# Convert a string representing a chain of associations and an attribute
|
45
41
|
# into the attribute itself
|
46
42
|
def contextualize(str)
|
47
|
-
parent, attr_name =
|
43
|
+
parent, attr_name = bind_pair_for(str)
|
48
44
|
table_for(parent)[attr_name]
|
49
45
|
end
|
50
46
|
|
@@ -62,32 +58,34 @@ module Ransack
|
|
62
58
|
end
|
63
59
|
|
64
60
|
def bind(object, str)
|
65
|
-
|
61
|
+
return nil unless str
|
62
|
+
object.parent, object.attr_name = bind_pair_for(str)
|
66
63
|
end
|
67
64
|
|
68
65
|
def traverse(str, base = @base)
|
69
|
-
str ||=
|
70
|
-
|
71
|
-
|
66
|
+
str ||= ''.freeze
|
67
|
+
segments = str.split(Constants::UNDERSCORE)
|
68
|
+
unless segments.empty?
|
72
69
|
remainder = []
|
73
70
|
found_assoc = nil
|
74
|
-
|
71
|
+
until found_assoc || segments.empty?
|
75
72
|
# Strip the _of_Model_type text from the association name, but hold
|
76
73
|
# onto it in klass, for use as the next base
|
77
74
|
assoc, klass = unpolymorphize_association(
|
78
75
|
segments.join(Constants::UNDERSCORE)
|
79
|
-
|
76
|
+
)
|
80
77
|
if found_assoc = get_association(assoc, base)
|
81
78
|
base = traverse(
|
82
|
-
remainder.join(
|
83
|
-
|
84
|
-
)
|
79
|
+
remainder.join(Constants::UNDERSCORE), klass || found_assoc.klass
|
80
|
+
)
|
85
81
|
end
|
86
82
|
|
87
83
|
remainder.unshift segments.pop
|
88
84
|
end
|
89
|
-
|
90
|
-
|
85
|
+
unless found_assoc
|
86
|
+
raise(UntraversableAssociationError,
|
87
|
+
"No association matches #{str}")
|
88
|
+
end
|
91
89
|
end
|
92
90
|
|
93
91
|
klassify(base)
|
@@ -95,22 +93,21 @@ module Ransack
|
|
95
93
|
|
96
94
|
def association_path(str, base = @base)
|
97
95
|
base = klassify(base)
|
98
|
-
str ||=
|
96
|
+
str ||= ''.freeze
|
99
97
|
path = []
|
100
|
-
segments = str.split(
|
98
|
+
segments = str.split(Constants::UNDERSCORE)
|
101
99
|
association_parts = []
|
102
|
-
|
103
|
-
while segments.
|
104
|
-
|
105
|
-
|
100
|
+
unless segments.empty?
|
101
|
+
while !segments.empty? &&
|
102
|
+
!base.columns_hash[segments.join(Constants::UNDERSCORE)] &&
|
103
|
+
association_parts << segments.shift
|
106
104
|
assoc, klass = unpolymorphize_association(
|
107
105
|
association_parts.join(Constants::UNDERSCORE)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
end
|
106
|
+
)
|
107
|
+
next unless found_assoc = get_association(assoc, base)
|
108
|
+
path += association_parts
|
109
|
+
association_parts = []
|
110
|
+
base = klassify(klass || found_assoc)
|
114
111
|
end
|
115
112
|
end
|
116
113
|
|
@@ -125,9 +122,13 @@ module Ransack
|
|
125
122
|
end
|
126
123
|
end
|
127
124
|
|
125
|
+
def ransackable_alias(str)
|
126
|
+
klass._ransack_aliases.fetch(str, str)
|
127
|
+
end
|
128
|
+
|
128
129
|
def ransackable_attribute?(str, klass)
|
129
130
|
klass.ransackable_attributes(auth_object).include?(str) ||
|
130
|
-
|
131
|
+
klass.ransortable_attributes(auth_object).include?(str)
|
131
132
|
end
|
132
133
|
|
133
134
|
def ransackable_association?(str, klass)
|
@@ -135,18 +136,22 @@ module Ransack
|
|
135
136
|
end
|
136
137
|
|
137
138
|
def ransackable_scope?(str, klass)
|
138
|
-
klass.ransackable_scopes(auth_object).any? { |s| s.
|
139
|
+
klass.ransackable_scopes(auth_object).any? { |s| s.to_sym == str.to_sym }
|
140
|
+
end
|
141
|
+
|
142
|
+
def ransackable_scope_skip_sanitize_args?(str, klass)
|
143
|
+
klass.ransackable_scopes_skip_sanitize_args.any? { |s| s.to_sym == str.to_sym }
|
139
144
|
end
|
140
145
|
|
141
|
-
def searchable_attributes(str =
|
146
|
+
def searchable_attributes(str = ''.freeze)
|
142
147
|
traverse(str).ransackable_attributes(auth_object)
|
143
148
|
end
|
144
149
|
|
145
|
-
def sortable_attributes(str =
|
150
|
+
def sortable_attributes(str = ''.freeze)
|
146
151
|
traverse(str).ransortable_attributes(auth_object)
|
147
152
|
end
|
148
153
|
|
149
|
-
def searchable_associations(str =
|
154
|
+
def searchable_associations(str = ''.freeze)
|
150
155
|
traverse(str).ransackable_associations(auth_object)
|
151
156
|
end
|
152
157
|
end
|
@@ -6,8 +6,14 @@ module ActionView::Helpers::Tags
|
|
6
6
|
# https://github.com/rails/rails/commit/c1a118a
|
7
7
|
class Base
|
8
8
|
private
|
9
|
-
|
10
|
-
|
9
|
+
if defined? ::ActiveRecord
|
10
|
+
def value
|
11
|
+
if @allow_method_names_outside_object
|
12
|
+
object.send @method_name if object && object.respond_to?(@method_name, true)
|
13
|
+
else
|
14
|
+
object.send @method_name if object
|
15
|
+
end
|
16
|
+
end
|
11
17
|
end
|
12
18
|
end
|
13
19
|
end
|
@@ -15,8 +21,7 @@ end
|
|
15
21
|
RANSACK_FORM_BUILDER = 'RANSACK_FORM_BUILDER'.freeze
|
16
22
|
|
17
23
|
require 'simple_form' if
|
18
|
-
(ENV[RANSACK_FORM_BUILDER] ||
|
19
|
-
.match('SimpleForm'.freeze)
|
24
|
+
(ENV[RANSACK_FORM_BUILDER] || ''.freeze).match('SimpleForm'.freeze)
|
20
25
|
|
21
26
|
module Ransack
|
22
27
|
module Helpers
|
@@ -47,7 +52,7 @@ module Ransack
|
|
47
52
|
raise ArgumentError, formbuilder_error_message(
|
48
53
|
"#{action}_select") unless object.respond_to?(:context)
|
49
54
|
options[:include_blank] = true unless options.has_key?(:include_blank)
|
50
|
-
bases = [
|
55
|
+
bases = [''.freeze].freeze + association_array(options[:associations])
|
51
56
|
if bases.size > 1
|
52
57
|
collection = attribute_collection_for_bases(action, bases)
|
53
58
|
object.name ||= default if can_use_default?(
|
@@ -66,13 +71,13 @@ module Ransack
|
|
66
71
|
def sort_direction_select(options = {}, html_options = {})
|
67
72
|
unless object.respond_to?(:context)
|
68
73
|
raise ArgumentError,
|
69
|
-
formbuilder_error_message(
|
74
|
+
formbuilder_error_message('sort_direction'.freeze)
|
70
75
|
end
|
71
76
|
template_collection_select(:dir, sort_array, options, html_options)
|
72
77
|
end
|
73
78
|
|
74
79
|
def sort_select(options = {}, html_options = {})
|
75
|
-
attribute_select(options, html_options,
|
80
|
+
attribute_select(options, html_options, 'sort'.freeze) +
|
76
81
|
sort_direction_select(options, html_options)
|
77
82
|
end
|
78
83
|
|
@@ -84,6 +89,10 @@ module Ransack
|
|
84
89
|
@template.sort_link @object, attribute, *args
|
85
90
|
end
|
86
91
|
|
92
|
+
def sort_url(attribute, *args)
|
93
|
+
@template.sort_url @object, attribute, *args
|
94
|
+
end
|
95
|
+
|
87
96
|
def condition_fields(*args, &block)
|
88
97
|
search_fields(:c, args, block)
|
89
98
|
end
|
@@ -135,7 +144,7 @@ module Ransack
|
|
135
144
|
else
|
136
145
|
only = Array.wrap(only).map(&:to_s)
|
137
146
|
keys = keys.select {
|
138
|
-
|k| only.include? k.sub(/_(any|all)$/,
|
147
|
+
|k| only.include? k.sub(/_(any|all)$/, ''.freeze)
|
139
148
|
}
|
140
149
|
end
|
141
150
|
end
|
@@ -177,9 +186,9 @@ module Ransack
|
|
177
186
|
|
178
187
|
def sort_array
|
179
188
|
[
|
180
|
-
[
|
181
|
-
[
|
182
|
-
]
|
189
|
+
['asc'.freeze, object.translate('asc'.freeze)].freeze,
|
190
|
+
['desc'.freeze, object.translate('desc'.freeze)].freeze
|
191
|
+
].freeze
|
183
192
|
end
|
184
193
|
|
185
194
|
def combinator_choices
|
@@ -234,7 +243,7 @@ module Ransack
|
|
234
243
|
Translate.association(base, :context => object.context),
|
235
244
|
collection_for_base(action, base)
|
236
245
|
]
|
237
|
-
rescue UntraversableAssociationError
|
246
|
+
rescue UntraversableAssociationError
|
238
247
|
nil
|
239
248
|
end
|
240
249
|
end
|