ransack 1.7.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.travis.yml +16 -48
- data/CHANGELOG.md +409 -26
- data/CONTRIBUTING.md +48 -20
- data/Gemfile +9 -13
- data/README.md +352 -92
- data/Rakefile +6 -25
- data/lib/polyamorous/activerecord_5.0_ruby_2/join_association.rb +2 -0
- data/lib/polyamorous/activerecord_5.0_ruby_2/join_dependency.rb +2 -0
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_association.rb +32 -0
- data/lib/polyamorous/activerecord_5.1_ruby_2/join_dependency.rb +112 -0
- data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_association.rb +32 -0
- data/lib/polyamorous/activerecord_5.2.0_ruby_2/join_dependency.rb +113 -0
- data/lib/polyamorous/activerecord_5.2.1_ruby_2/join_association.rb +31 -0
- data/lib/polyamorous/activerecord_5.2.1_ruby_2/join_dependency.rb +57 -0
- data/lib/polyamorous/join.rb +70 -0
- data/lib/polyamorous/swapping_reflection_class.rb +11 -0
- data/lib/polyamorous/tree_node.rb +7 -0
- data/lib/polyamorous.rb +25 -0
- data/lib/ransack/adapters/active_record/base.rb +23 -2
- data/lib/ransack/adapters/active_record/context.rb +210 -135
- data/lib/ransack/adapters/active_record/ransack/constants.rb +53 -53
- data/lib/ransack/adapters/active_record/ransack/context.rb +11 -15
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +33 -30
- 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 +45 -23
- data/lib/ransack/configuration.rb +91 -4
- data/lib/ransack/constants.rb +14 -26
- data/lib/ransack/context.rb +29 -18
- data/lib/ransack/helpers/form_builder.rb +27 -12
- data/lib/ransack/helpers/form_helper.rb +75 -70
- 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/da.yml +70 -0
- data/lib/ransack/locale/el.yml +70 -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/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 +5 -2
- data/lib/ransack/nodes/bindable.rb +18 -6
- data/lib/ransack/nodes/condition.rb +77 -28
- data/lib/ransack/nodes/grouping.rb +16 -10
- data/lib/ransack/nodes/sort.rb +9 -5
- data/lib/ransack/nodes/value.rb +74 -68
- data/lib/ransack/nodes.rb +1 -1
- data/lib/ransack/predicate.rb +15 -19
- data/lib/ransack/search.rb +14 -7
- data/lib/ransack/translate.rb +3 -3
- data/lib/ransack/version.rb +1 -1
- data/lib/ransack/visitor.rb +1 -12
- data/lib/ransack.rb +7 -7
- 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 -10
- data/spec/console.rb +4 -0
- data/spec/helpers/polyamorous_helper.rb +24 -0
- data/spec/ransack/adapters/active_record/base_spec.rb +365 -74
- data/spec/ransack/adapters/active_record/context_spec.rb +14 -19
- 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/join_association_spec.rb +28 -0
- data/spec/ransack/join_dependency_spec.rb +86 -0
- data/spec/ransack/join_spec.rb +19 -0
- data/spec/ransack/nodes/condition_spec.rb +24 -0
- data/spec/ransack/nodes/grouping_spec.rb +56 -0
- data/spec/ransack/predicate_spec.rb +27 -5
- data/spec/ransack/search_spec.rb +84 -70
- data/spec/spec_helper.rb +4 -0
- data/spec/support/schema.rb +86 -41
- metadata +60 -81
- data/lib/ransack/adapters/active_record/3.0/compat.rb +0 -179
- data/lib/ransack/adapters/active_record/3.0/context.rb +0 -201
- data/lib/ransack/adapters/active_record/3.1/context.rb +0 -215
- 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 -130
- 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 -12
@@ -3,48 +3,51 @@ 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 = attribute.attr.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] = format_values_for(predicate.right[0])
|
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
|
-
|
47
|
-
|
46
|
+
predicate.class == Arel::Nodes::In
|
47
|
+
end
|
48
|
+
|
49
|
+
def casted_array?(predicate)
|
50
|
+
predicate.respond_to?(:val) && predicate.val.is_a?(Array)
|
48
51
|
end
|
49
52
|
|
50
53
|
def format_values_for(predicate)
|
@@ -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.to_s.freeze
|
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'
|
data/lib/ransack/adapters.rb
CHANGED
@@ -1,42 +1,64 @@
|
|
1
1
|
module Ransack
|
2
2
|
module Adapters
|
3
3
|
|
4
|
-
def self.
|
5
|
-
@
|
6
|
-
:active_record => defined?(::ActiveRecord::Base),
|
7
|
-
:mongoid => defined?(::Mongoid) && !defined?(::ActiveRecord::Base)
|
8
|
-
}
|
4
|
+
def self.object_mapper
|
5
|
+
@object_mapper ||= instantiate_object_mapper
|
9
6
|
end
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
13
16
|
end
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
class ActiveRecordAdapter
|
19
|
+
def require_constants
|
20
|
+
require 'ransack/adapters/active_record/ransack/constants'
|
21
|
+
end
|
22
|
+
|
23
|
+
def require_adapter
|
17
24
|
require 'ransack/adapters/active_record/ransack/translate'
|
18
25
|
require 'ransack/adapters/active_record'
|
19
26
|
end
|
20
27
|
|
21
|
-
|
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
|
22
47
|
require 'ransack/adapters/mongoid/ransack/translate'
|
23
48
|
require 'ransack/adapters/mongoid'
|
24
49
|
end
|
25
|
-
end
|
26
50
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
51
|
+
def require_context
|
52
|
+
require 'ransack/adapters/mongoid/ransack/visitor'
|
53
|
+
end
|
31
54
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
55
|
+
def require_nodes
|
56
|
+
require 'ransack/adapters/mongoid/ransack/nodes/condition'
|
57
|
+
end
|
36
58
|
|
37
|
-
|
38
|
-
|
39
|
-
|
59
|
+
def require_search
|
60
|
+
require 'ransack/adapters/mongoid/ransack/context'
|
61
|
+
end
|
40
62
|
end
|
41
63
|
end
|
42
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,9 @@ module Ransack
|
|
59
45
|
NOT_EQ_ALL = 'not_eq_all'.freeze
|
60
46
|
CONT = 'cont'.freeze
|
61
47
|
|
62
|
-
|
48
|
+
RAILS_5_1 = '5.1'.freeze
|
49
|
+
RAILS_5_2 = '5.2'.freeze
|
50
|
+
RAILS_5_2_0 = '5.2.0'.freeze
|
63
51
|
|
64
52
|
RANSACK_SLASH_SEARCHES = 'ransack/searches'.freeze
|
65
53
|
RANSACK_SLASH_SEARCHES_SLASH_SEARCH = 'ransack/searches/search'.freeze
|
data/lib/ransack/context.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'ransack/visitor'
|
2
|
-
Ransack::Adapters.require_context
|
2
|
+
Ransack::Adapters.object_mapper.require_context
|
3
3
|
|
4
4
|
module Ransack
|
5
5
|
class Context
|
@@ -17,9 +17,12 @@ module Ransack
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def for(object, options = {})
|
20
|
-
context =
|
21
|
-
|
22
|
-
|
20
|
+
context =
|
21
|
+
if Class === object
|
22
|
+
for_class(object, options)
|
23
|
+
else
|
24
|
+
for_object(object, options)
|
25
|
+
end
|
23
26
|
context or raise ArgumentError,
|
24
27
|
"Don't know what context to use for #{object}"
|
25
28
|
end
|
@@ -37,7 +40,7 @@ module Ransack
|
|
37
40
|
# Convert a string representing a chain of associations and an attribute
|
38
41
|
# into the attribute itself
|
39
42
|
def contextualize(str)
|
40
|
-
parent, attr_name =
|
43
|
+
parent, attr_name = bind_pair_for(str)
|
41
44
|
table_for(parent)[attr_name]
|
42
45
|
end
|
43
46
|
|
@@ -55,13 +58,14 @@ module Ransack
|
|
55
58
|
end
|
56
59
|
|
57
60
|
def bind(object, str)
|
58
|
-
|
61
|
+
return nil unless str
|
62
|
+
object.parent, object.attr_name = bind_pair_for(str)
|
59
63
|
end
|
60
64
|
|
61
65
|
def traverse(str, base = @base)
|
62
|
-
str ||=
|
66
|
+
str ||= ''.freeze
|
63
67
|
|
64
|
-
if (segments = str.split(
|
68
|
+
if (segments = str.split(Constants::UNDERSCORE)).size > 0
|
65
69
|
remainder = []
|
66
70
|
found_assoc = nil
|
67
71
|
while !found_assoc && segments.size > 0 do
|
@@ -72,9 +76,8 @@ module Ransack
|
|
72
76
|
)
|
73
77
|
if found_assoc = get_association(assoc, base)
|
74
78
|
base = traverse(
|
75
|
-
remainder.join(
|
76
|
-
|
77
|
-
)
|
79
|
+
remainder.join(Constants::UNDERSCORE), klass || found_assoc.klass
|
80
|
+
)
|
78
81
|
end
|
79
82
|
|
80
83
|
remainder.unshift segments.pop
|
@@ -88,11 +91,11 @@ module Ransack
|
|
88
91
|
|
89
92
|
def association_path(str, base = @base)
|
90
93
|
base = klassify(base)
|
91
|
-
str ||=
|
94
|
+
str ||= ''.freeze
|
92
95
|
path = []
|
93
|
-
segments = str.split(
|
96
|
+
segments = str.split(Constants::UNDERSCORE)
|
94
97
|
association_parts = []
|
95
|
-
if (segments = str.split(
|
98
|
+
if (segments = str.split(Constants::UNDERSCORE)).size > 0
|
96
99
|
while segments.size > 0 &&
|
97
100
|
!base.columns_hash[segments.join(Constants::UNDERSCORE)] &&
|
98
101
|
association_parts << segments.shift do
|
@@ -118,6 +121,10 @@ module Ransack
|
|
118
121
|
end
|
119
122
|
end
|
120
123
|
|
124
|
+
def ransackable_alias(str)
|
125
|
+
klass._ransack_aliases.fetch(str, str)
|
126
|
+
end
|
127
|
+
|
121
128
|
def ransackable_attribute?(str, klass)
|
122
129
|
klass.ransackable_attributes(auth_object).include?(str) ||
|
123
130
|
klass.ransortable_attributes(auth_object).include?(str)
|
@@ -128,18 +135,22 @@ module Ransack
|
|
128
135
|
end
|
129
136
|
|
130
137
|
def ransackable_scope?(str, klass)
|
131
|
-
klass.ransackable_scopes(auth_object).any? { |s| s.
|
138
|
+
klass.ransackable_scopes(auth_object).any? { |s| s.to_sym == str.to_sym }
|
139
|
+
end
|
140
|
+
|
141
|
+
def ransackable_scope_skip_sanitize_args?(str, klass)
|
142
|
+
klass.ransackable_scopes_skip_sanitize_args.any? { |s| s.to_sym == str.to_sym }
|
132
143
|
end
|
133
144
|
|
134
|
-
def searchable_attributes(str =
|
145
|
+
def searchable_attributes(str = ''.freeze)
|
135
146
|
traverse(str).ransackable_attributes(auth_object)
|
136
147
|
end
|
137
148
|
|
138
|
-
def sortable_attributes(str =
|
149
|
+
def sortable_attributes(str = ''.freeze)
|
139
150
|
traverse(str).ransortable_attributes(auth_object)
|
140
151
|
end
|
141
152
|
|
142
|
-
def searchable_associations(str =
|
153
|
+
def searchable_associations(str = ''.freeze)
|
143
154
|
traverse(str).ransackable_associations(auth_object)
|
144
155
|
end
|
145
156
|
end
|
@@ -6,8 +6,20 @@ 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
|
+
if ::ActiveRecord::VERSION::STRING < '5.2'
|
11
|
+
def value(object)
|
12
|
+
object.send @method_name if object # use send instead of public_send
|
13
|
+
end
|
14
|
+
else # rails/rails#29791
|
15
|
+
def value
|
16
|
+
if @allow_method_names_outside_object
|
17
|
+
object.send @method_name if object && object.respond_to?(@method_name, true)
|
18
|
+
else
|
19
|
+
object.send @method_name if object
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
11
23
|
end
|
12
24
|
end
|
13
25
|
end
|
@@ -15,8 +27,7 @@ end
|
|
15
27
|
RANSACK_FORM_BUILDER = 'RANSACK_FORM_BUILDER'.freeze
|
16
28
|
|
17
29
|
require 'simple_form' if
|
18
|
-
(ENV[RANSACK_FORM_BUILDER] ||
|
19
|
-
.match('SimpleForm'.freeze)
|
30
|
+
(ENV[RANSACK_FORM_BUILDER] || ''.freeze).match('SimpleForm'.freeze)
|
20
31
|
|
21
32
|
module Ransack
|
22
33
|
module Helpers
|
@@ -47,7 +58,7 @@ module Ransack
|
|
47
58
|
raise ArgumentError, formbuilder_error_message(
|
48
59
|
"#{action}_select") unless object.respond_to?(:context)
|
49
60
|
options[:include_blank] = true unless options.has_key?(:include_blank)
|
50
|
-
bases = [
|
61
|
+
bases = [''.freeze].freeze + association_array(options[:associations])
|
51
62
|
if bases.size > 1
|
52
63
|
collection = attribute_collection_for_bases(action, bases)
|
53
64
|
object.name ||= default if can_use_default?(
|
@@ -66,13 +77,13 @@ module Ransack
|
|
66
77
|
def sort_direction_select(options = {}, html_options = {})
|
67
78
|
unless object.respond_to?(:context)
|
68
79
|
raise ArgumentError,
|
69
|
-
formbuilder_error_message(
|
80
|
+
formbuilder_error_message('sort_direction'.freeze)
|
70
81
|
end
|
71
82
|
template_collection_select(:dir, sort_array, options, html_options)
|
72
83
|
end
|
73
84
|
|
74
85
|
def sort_select(options = {}, html_options = {})
|
75
|
-
attribute_select(options, html_options,
|
86
|
+
attribute_select(options, html_options, 'sort'.freeze) +
|
76
87
|
sort_direction_select(options, html_options)
|
77
88
|
end
|
78
89
|
|
@@ -84,6 +95,10 @@ module Ransack
|
|
84
95
|
@template.sort_link @object, attribute, *args
|
85
96
|
end
|
86
97
|
|
98
|
+
def sort_url(attribute, *args)
|
99
|
+
@template.sort_url @object, attribute, *args
|
100
|
+
end
|
101
|
+
|
87
102
|
def condition_fields(*args, &block)
|
88
103
|
search_fields(:c, args, block)
|
89
104
|
end
|
@@ -135,7 +150,7 @@ module Ransack
|
|
135
150
|
else
|
136
151
|
only = Array.wrap(only).map(&:to_s)
|
137
152
|
keys = keys.select {
|
138
|
-
|k| only.include? k.sub(/_(any|all)$/,
|
153
|
+
|k| only.include? k.sub(/_(any|all)$/, ''.freeze)
|
139
154
|
}
|
140
155
|
end
|
141
156
|
end
|
@@ -177,9 +192,9 @@ module Ransack
|
|
177
192
|
|
178
193
|
def sort_array
|
179
194
|
[
|
180
|
-
[
|
181
|
-
[
|
182
|
-
]
|
195
|
+
['asc'.freeze, object.translate('asc'.freeze)].freeze,
|
196
|
+
['desc'.freeze, object.translate('desc'.freeze)].freeze
|
197
|
+
].freeze
|
183
198
|
end
|
184
199
|
|
185
200
|
def combinator_choices
|
@@ -234,7 +249,7 @@ module Ransack
|
|
234
249
|
Translate.association(base, :context => object.context),
|
235
250
|
collection_for_base(action, base)
|
236
251
|
]
|
237
|
-
rescue UntraversableAssociationError
|
252
|
+
rescue UntraversableAssociationError
|
238
253
|
nil
|
239
254
|
end
|
240
255
|
end
|