ransack 1.7.0 → 1.8.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/.travis.yml +40 -22
- data/CHANGELOG.md +176 -27
- data/CONTRIBUTING.md +30 -19
- data/Gemfile +8 -3
- data/README.md +131 -58
- data/Rakefile +5 -2
- data/lib/ransack.rb +10 -5
- data/lib/ransack/adapters.rb +43 -23
- data/lib/ransack/adapters/active_record.rb +2 -2
- data/lib/ransack/adapters/active_record/3.0/compat.rb +5 -5
- data/lib/ransack/adapters/active_record/3.0/context.rb +5 -3
- data/lib/ransack/adapters/active_record/3.1/context.rb +1 -4
- data/lib/ransack/adapters/active_record/base.rb +12 -1
- data/lib/ransack/adapters/active_record/context.rb +148 -55
- data/lib/ransack/adapters/active_record/ransack/constants.rb +53 -53
- data/lib/ransack/adapters/active_record/ransack/context.rb +3 -1
- data/lib/ransack/adapters/active_record/ransack/nodes/condition.rb +20 -28
- data/lib/ransack/adapters/mongoid/base.rb +21 -6
- data/lib/ransack/adapters/mongoid/context.rb +9 -5
- data/lib/ransack/configuration.rb +24 -3
- data/lib/ransack/constants.rb +11 -22
- data/lib/ransack/context.rb +20 -13
- data/lib/ransack/helpers/form_builder.rb +5 -6
- data/lib/ransack/helpers/form_helper.rb +50 -69
- data/lib/ransack/locale/da.yml +70 -0
- data/lib/ransack/locale/id.yml +70 -0
- data/lib/ransack/locale/ja.yml +70 -0
- data/lib/ransack/locale/pt-BR.yml +70 -0
- data/lib/ransack/locale/{zh.yml → zh-CN.yml} +1 -1
- data/lib/ransack/locale/zh-TW.yml +70 -0
- data/lib/ransack/nodes.rb +1 -1
- data/lib/ransack/nodes/attribute.rb +4 -1
- data/lib/ransack/nodes/bindable.rb +18 -6
- data/lib/ransack/nodes/condition.rb +58 -28
- data/lib/ransack/nodes/grouping.rb +15 -4
- data/lib/ransack/nodes/sort.rb +9 -5
- data/lib/ransack/predicate.rb +6 -2
- data/lib/ransack/search.rb +6 -5
- data/lib/ransack/translate.rb +2 -2
- data/lib/ransack/version.rb +1 -1
- data/ransack.gemspec +4 -4
- data/spec/mongoid/adapters/mongoid/base_spec.rb +20 -1
- data/spec/mongoid/nodes/condition_spec.rb +15 -0
- data/spec/mongoid/support/mongoid.yml +5 -0
- data/spec/mongoid/support/schema.rb +4 -0
- data/spec/mongoid_spec_helper.rb +13 -9
- data/spec/ransack/adapters/active_record/base_spec.rb +249 -71
- data/spec/ransack/adapters/active_record/context_spec.rb +16 -18
- data/spec/ransack/helpers/form_builder_spec.rb +5 -2
- data/spec/ransack/helpers/form_helper_spec.rb +84 -14
- data/spec/ransack/nodes/condition_spec.rb +24 -0
- data/spec/ransack/nodes/grouping_spec.rb +56 -0
- data/spec/ransack/predicate_spec.rb +5 -5
- data/spec/ransack/search_spec.rb +79 -70
- data/spec/support/schema.rb +43 -29
- metadata +17 -12
@@ -27,6 +27,8 @@ module Ransack
|
|
27
27
|
@join_dependency = join_dependency(@object)
|
28
28
|
@join_type = options[:join_type] || Polyamorous::OuterJoin
|
29
29
|
@search_key = options[:search_key] || Ransack.options[:search_key]
|
30
|
+
@associations_pot = {}
|
31
|
+
@lock_associations = []
|
30
32
|
|
31
33
|
if ::ActiveRecord::VERSION::STRING >= Constants::RAILS_4_1
|
32
34
|
@base = @join_dependency.join_root
|
@@ -40,7 +42,7 @@ module Ransack
|
|
40
42
|
@base.table_name, as: @base.aliased_table_name, type_caster: self
|
41
43
|
)
|
42
44
|
@bind_pairs = Hash.new do |hash, key|
|
43
|
-
parent, attr_name = get_parent_and_attribute_name(key
|
45
|
+
parent, attr_name = get_parent_and_attribute_name(key)
|
44
46
|
if parent && attr_name
|
45
47
|
hash[key] = [parent, attr_name]
|
46
48
|
end
|
@@ -3,41 +3,33 @@ 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
|
+
query.where(format_predicate(attribute).not)
|
11
|
+
context.remove_association(association)
|
12
|
+
Arel::Nodes::NotIn.new(context.primary_key, Arel.sql(query.to_sql))
|
13
|
+
else
|
14
|
+
format_predicate(attribute)
|
15
|
+
end
|
16
|
+
}.reduce(combinator_method)
|
7
17
|
end
|
8
18
|
|
9
19
|
private
|
10
20
|
|
11
|
-
def
|
12
|
-
|
13
|
-
a.attr.send(
|
14
|
-
arel_predicate_for_attribute(a), formatted_values_for_attribute(a)
|
15
|
-
)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def arel_predicate_for(predicates)
|
20
|
-
if predicates.size > 1
|
21
|
-
combinator_for(predicates)
|
22
|
-
else
|
23
|
-
format_predicate(predicates.first)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def combinator_for(predicates)
|
28
|
-
if combinator === Constants::AND
|
29
|
-
Arel::Nodes::Grouping.new(Arel::Nodes::And.new(predicates))
|
30
|
-
elsif combinator === Constants::OR
|
31
|
-
predicates.inject(&:or)
|
32
|
-
end
|
21
|
+
def combinator_method
|
22
|
+
combinator === Constants::OR ? :or : :and
|
33
23
|
end
|
34
24
|
|
35
|
-
def format_predicate(
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
25
|
+
def format_predicate(attribute)
|
26
|
+
arel_pred = arel_predicate_for_attribute(attribute)
|
27
|
+
arel_values = formatted_values_for_attribute(attribute)
|
28
|
+
predicate = attribute.attr.public_send(arel_pred, arel_values)
|
29
|
+
if casted_array_with_in_predicate?(predicate)
|
30
|
+
predicate.right[0] = format_values_for(predicate.right[0])
|
40
31
|
end
|
32
|
+
predicate
|
41
33
|
end
|
42
34
|
|
43
35
|
def casted_array_with_in_predicate?(predicate)
|
@@ -33,6 +33,14 @@ module Ransack
|
|
33
33
|
end
|
34
34
|
|
35
35
|
module ClassMethods
|
36
|
+
def _ransack_aliases
|
37
|
+
@_ransack_aliases ||= {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def _ransack_aliases=(value)
|
41
|
+
@_ransack_aliases = value
|
42
|
+
end
|
43
|
+
|
36
44
|
def _ransackers
|
37
45
|
@_ransackers ||= {}
|
38
46
|
end
|
@@ -49,13 +57,18 @@ module Ransack
|
|
49
57
|
|
50
58
|
alias_method :search, :ransack
|
51
59
|
|
60
|
+
def ransack_alias(new_name, old_name)
|
61
|
+
self._ransack_aliases.store(new_name.to_s, old_name.to_s)
|
62
|
+
end
|
63
|
+
|
52
64
|
def ransacker(name, opts = {}, &block)
|
53
65
|
self._ransackers = _ransackers.merge name.to_s => Ransacker
|
54
66
|
.new(self, name, opts, &block)
|
55
67
|
end
|
56
68
|
|
57
69
|
def all_ransackable_attributes
|
58
|
-
['id'] + column_names.select { |c| c != '_id' } + _ransackers.keys
|
70
|
+
['id'] + column_names.select { |c| c != '_id' } + _ransackers.keys +
|
71
|
+
_ransack_aliases.keys
|
59
72
|
end
|
60
73
|
|
61
74
|
def ransackable_attributes(auth_object = nil)
|
@@ -73,7 +86,9 @@ module Ransack
|
|
73
86
|
end
|
74
87
|
|
75
88
|
def reflect_on_all_associations_all
|
76
|
-
reflect_on_all_associations(
|
89
|
+
reflect_on_all_associations(
|
90
|
+
:belongs_to, :has_one, :has_many, :embeds_many, :embedded_in
|
91
|
+
)
|
77
92
|
end
|
78
93
|
|
79
94
|
# For overriding with a whitelist of symbols
|
@@ -116,10 +131,10 @@ module Ransack
|
|
116
131
|
end
|
117
132
|
|
118
133
|
def table
|
119
|
-
name = ::Ransack::Adapters::Mongoid::Attributes::Attribute.new(
|
120
|
-
|
121
|
-
|
122
|
-
}
|
134
|
+
name = ::Ransack::Adapters::Mongoid::Attributes::Attribute.new(
|
135
|
+
self.criteria, :name
|
136
|
+
)
|
137
|
+
{ :name => name }
|
123
138
|
end
|
124
139
|
|
125
140
|
end
|
@@ -6,10 +6,6 @@ module Ransack
|
|
6
6
|
module Mongoid
|
7
7
|
class Context < ::Ransack::Context
|
8
8
|
|
9
|
-
# Because the AR::Associations namespace is insane
|
10
|
-
# JoinDependency = ::Mongoid::Associations::JoinDependency
|
11
|
-
# JoinPart = JoinDependency::JoinPart
|
12
|
-
|
13
9
|
def initialize(object, options = {})
|
14
10
|
super
|
15
11
|
# @arel_visitor = @engine.connection.visitor
|
@@ -100,6 +96,14 @@ module Ransack
|
|
100
96
|
end
|
101
97
|
end
|
102
98
|
|
99
|
+
def lock_association(association)
|
100
|
+
warn "lock_association is not implemented for Ransack mongoid adapter" if $DEBUG
|
101
|
+
end
|
102
|
+
|
103
|
+
def remove_association(association)
|
104
|
+
warn "remove_association is not implemented for Ransack mongoid adapter" if $DEBUG
|
105
|
+
end
|
106
|
+
|
103
107
|
private
|
104
108
|
|
105
109
|
def get_parent_and_attribute_name(str, parent = @base)
|
@@ -132,7 +136,7 @@ module Ransack
|
|
132
136
|
end
|
133
137
|
|
134
138
|
def join_dependency(relation)
|
135
|
-
if relation.respond_to?(:join_dependency) #
|
139
|
+
if relation.respond_to?(:join_dependency) # Polyamorous enables this
|
136
140
|
relation.join_dependency
|
137
141
|
else
|
138
142
|
build_join_dependency(relation)
|
@@ -8,7 +8,8 @@ module Ransack
|
|
8
8
|
self.predicates = {}
|
9
9
|
self.options = {
|
10
10
|
:search_key => :q,
|
11
|
-
:ignore_unknown_conditions => true
|
11
|
+
:ignore_unknown_conditions => true,
|
12
|
+
:hide_sort_order_indicators => false
|
12
13
|
}
|
13
14
|
|
14
15
|
def configure
|
@@ -61,12 +62,32 @@ module Ransack
|
|
61
62
|
self.options[:search_key] = name
|
62
63
|
end
|
63
64
|
|
64
|
-
#
|
65
|
-
# into a search.
|
65
|
+
# By default Ransack ignores errors if an unknown predicate, condition or
|
66
|
+
# attribute is passed into a search. The default may be overridden in an
|
67
|
+
# initializer file like `config/initializers/ransack.rb` as follows:
|
68
|
+
#
|
69
|
+
# Ransack.configure do |config|
|
70
|
+
# # Raise if an unknown predicate, condition or attribute is passed
|
71
|
+
# config.ignore_unknown_conditions = false
|
72
|
+
# end
|
73
|
+
#
|
66
74
|
def ignore_unknown_conditions=(boolean)
|
67
75
|
self.options[:ignore_unknown_conditions] = boolean
|
68
76
|
end
|
69
77
|
|
78
|
+
# By default, Ransack displays sort order indicator arrows in sort links.
|
79
|
+
# The default may be globally overridden in an initializer file like
|
80
|
+
# `config/initializers/ransack.rb` as follows:
|
81
|
+
#
|
82
|
+
# Ransack.configure do |config|
|
83
|
+
# # Hide sort link order indicators globally across the application
|
84
|
+
# config.hide_sort_order_indicators = true
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
def hide_sort_order_indicators=(boolean)
|
88
|
+
self.options[:hide_sort_order_indicators] = boolean
|
89
|
+
end
|
90
|
+
|
70
91
|
def arel_predicate_with_suffix(arel_predicate, suffix)
|
71
92
|
if arel_predicate === Proc
|
72
93
|
proc { |v| "#{arel_predicate.call(v)}#{suffix}" }
|
data/lib/ransack/constants.rb
CHANGED
@@ -1,19 +1,10 @@
|
|
1
1
|
module Ransack
|
2
2
|
module Constants
|
3
|
-
ASC = 'asc'.freeze
|
4
|
-
DESC = 'desc'.freeze
|
5
|
-
ASC_DESC = [ASC, DESC].freeze
|
6
|
-
|
7
3
|
ASC_ARROW = '▲'.freeze
|
8
4
|
DESC_ARROW = '▼'.freeze
|
9
5
|
|
10
6
|
OR = 'or'.freeze
|
11
7
|
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
8
|
|
18
9
|
CAP_SEARCH = 'Search'.freeze
|
19
10
|
SEARCH = 'search'.freeze
|
@@ -23,17 +14,12 @@ module Ransack
|
|
23
14
|
ATTRIBUTES = 'attributes'.freeze
|
24
15
|
COMBINATOR = 'combinator'.freeze
|
25
16
|
|
26
|
-
SPACE = ' '.freeze
|
27
|
-
COMMA_SPACE = ', '.freeze
|
28
|
-
COLON_SPACE = ': '.freeze
|
29
17
|
TWO_COLONS = '::'.freeze
|
30
18
|
UNDERSCORE = '_'.freeze
|
31
19
|
LEFT_PARENTHESIS = '('.freeze
|
32
20
|
Q = 'q'.freeze
|
33
21
|
I = 'i'.freeze
|
34
|
-
NON_BREAKING_SPACE = ' '.freeze
|
35
22
|
DOT_ASTERIX = '.*'.freeze
|
36
|
-
EMPTY = ''.freeze
|
37
23
|
|
38
24
|
STRING_JOIN = 'string_join'.freeze
|
39
25
|
ASSOCIATION_JOIN = 'association_join'.freeze
|
@@ -44,14 +30,17 @@ module Ransack
|
|
44
30
|
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
|
45
31
|
BOOLEAN_VALUES = (TRUE_VALUES + FALSE_VALUES).freeze
|
46
32
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
33
|
+
AND_OR = ['and'.freeze, 'or'.freeze].freeze
|
34
|
+
IN_NOT_IN = ['in'.freeze, 'not_in'.freeze].freeze
|
35
|
+
SUFFIXES = ['_any'.freeze, '_all'.freeze].freeze
|
36
|
+
AREL_PREDICATES = [
|
37
|
+
'eq'.freeze, 'not_eq'.freeze,
|
38
|
+
'matches'.freeze, 'does_not_match'.freeze,
|
39
|
+
'lt'.freeze, 'lteq'.freeze,
|
40
|
+
'gt'.freeze, 'gteq'.freeze,
|
41
|
+
'in'.freeze, 'not_in'.freeze
|
42
|
+
].freeze
|
43
|
+
A_S_I = ['a'.freeze, 's'.freeze, 'i'.freeze].freeze
|
55
44
|
|
56
45
|
EQ = 'eq'.freeze
|
57
46
|
NOT_EQ = 'not_eq'.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
|
@@ -55,11 +58,12 @@ module Ransack
|
|
55
58
|
end
|
56
59
|
|
57
60
|
def bind(object, str)
|
61
|
+
return nil unless str
|
58
62
|
object.parent, object.attr_name = @bind_pairs[str]
|
59
63
|
end
|
60
64
|
|
61
65
|
def traverse(str, base = @base)
|
62
|
-
str ||=
|
66
|
+
str ||= ''.freeze
|
63
67
|
|
64
68
|
if (segments = str.split(/_/)).size > 0
|
65
69
|
remainder = []
|
@@ -68,13 +72,12 @@ module Ransack
|
|
68
72
|
# Strip the _of_Model_type text from the association name, but hold
|
69
73
|
# onto it in klass, for use as the next base
|
70
74
|
assoc, klass = unpolymorphize_association(
|
71
|
-
segments.join(
|
75
|
+
segments.join('_'.freeze)
|
72
76
|
)
|
73
77
|
if found_assoc = get_association(assoc, base)
|
74
78
|
base = traverse(
|
75
|
-
remainder.join(
|
76
|
-
|
77
|
-
)
|
79
|
+
remainder.join('_'.freeze), klass || found_assoc.klass
|
80
|
+
)
|
78
81
|
end
|
79
82
|
|
80
83
|
remainder.unshift segments.pop
|
@@ -88,7 +91,7 @@ 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
96
|
segments = str.split(/_/)
|
94
97
|
association_parts = []
|
@@ -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)
|
@@ -131,15 +138,15 @@ module Ransack
|
|
131
138
|
klass.ransackable_scopes(auth_object).any? { |s| s.to_s == str }
|
132
139
|
end
|
133
140
|
|
134
|
-
def searchable_attributes(str =
|
141
|
+
def searchable_attributes(str = ''.freeze)
|
135
142
|
traverse(str).ransackable_attributes(auth_object)
|
136
143
|
end
|
137
144
|
|
138
|
-
def sortable_attributes(str =
|
145
|
+
def sortable_attributes(str = ''.freeze)
|
139
146
|
traverse(str).ransortable_attributes(auth_object)
|
140
147
|
end
|
141
148
|
|
142
|
-
def searchable_associations(str =
|
149
|
+
def searchable_associations(str = ''.freeze)
|
143
150
|
traverse(str).ransackable_associations(auth_object)
|
144
151
|
end
|
145
152
|
end
|
@@ -15,8 +15,7 @@ end
|
|
15
15
|
RANSACK_FORM_BUILDER = 'RANSACK_FORM_BUILDER'.freeze
|
16
16
|
|
17
17
|
require 'simple_form' if
|
18
|
-
(ENV[RANSACK_FORM_BUILDER] ||
|
19
|
-
.match('SimpleForm'.freeze)
|
18
|
+
(ENV[RANSACK_FORM_BUILDER] || ''.freeze).match('SimpleForm'.freeze)
|
20
19
|
|
21
20
|
module Ransack
|
22
21
|
module Helpers
|
@@ -47,7 +46,7 @@ module Ransack
|
|
47
46
|
raise ArgumentError, formbuilder_error_message(
|
48
47
|
"#{action}_select") unless object.respond_to?(:context)
|
49
48
|
options[:include_blank] = true unless options.has_key?(:include_blank)
|
50
|
-
bases = [
|
49
|
+
bases = [''.freeze].freeze + association_array(options[:associations])
|
51
50
|
if bases.size > 1
|
52
51
|
collection = attribute_collection_for_bases(action, bases)
|
53
52
|
object.name ||= default if can_use_default?(
|
@@ -66,13 +65,13 @@ module Ransack
|
|
66
65
|
def sort_direction_select(options = {}, html_options = {})
|
67
66
|
unless object.respond_to?(:context)
|
68
67
|
raise ArgumentError,
|
69
|
-
formbuilder_error_message(
|
68
|
+
formbuilder_error_message('sort_direction'.freeze)
|
70
69
|
end
|
71
70
|
template_collection_select(:dir, sort_array, options, html_options)
|
72
71
|
end
|
73
72
|
|
74
73
|
def sort_select(options = {}, html_options = {})
|
75
|
-
attribute_select(options, html_options,
|
74
|
+
attribute_select(options, html_options, 'sort'.freeze) +
|
76
75
|
sort_direction_select(options, html_options)
|
77
76
|
end
|
78
77
|
|
@@ -135,7 +134,7 @@ module Ransack
|
|
135
134
|
else
|
136
135
|
only = Array.wrap(only).map(&:to_s)
|
137
136
|
keys = keys.select {
|
138
|
-
|k| only.include? k.sub(/_(any|all)$/,
|
137
|
+
|k| only.include? k.sub(/_(any|all)$/, ''.freeze)
|
139
138
|
}
|
140
139
|
end
|
141
140
|
end
|
@@ -38,43 +38,41 @@ module Ransack
|
|
38
38
|
#
|
39
39
|
# <%= sort_link(@q, :name, [:name, 'kind ASC'], 'Player Name') %>
|
40
40
|
#
|
41
|
-
|
41
|
+
# You can also use a block:
|
42
|
+
#
|
43
|
+
# <%= sort_link(@q, :name, [:name, 'kind ASC']) do %>
|
44
|
+
# <strong>Player Name</strong>
|
45
|
+
# <% end %>
|
46
|
+
#
|
47
|
+
def sort_link(search_object, attribute, *args, &block)
|
42
48
|
search, routing_proxy = extract_search_and_routing_proxy(search_object)
|
43
49
|
unless Search === search
|
44
50
|
raise TypeError, 'First argument must be a Ransack::Search!'
|
45
51
|
end
|
46
|
-
|
52
|
+
args.unshift(capture(&block)) if block_given?
|
53
|
+
s = SortLink.new(search, attribute, args, params, &block)
|
47
54
|
link_to(s.name, url(routing_proxy, s.url_options), s.html_options(args))
|
48
55
|
end
|
49
56
|
|
50
57
|
private
|
51
58
|
|
52
59
|
def options_for(record)
|
53
|
-
record.map
|
60
|
+
record.map { |r| parse_record(r) }
|
54
61
|
end
|
55
62
|
|
56
63
|
def parse_record(object)
|
57
|
-
if object.is_a?(Ransack::Search)
|
58
|
-
|
59
|
-
else
|
60
|
-
object
|
61
|
-
end
|
64
|
+
return object.klass if object.is_a?(Ransack::Search)
|
65
|
+
object
|
62
66
|
end
|
63
67
|
|
64
68
|
def html_option_for(option, search)
|
65
|
-
if option.present?
|
66
|
-
|
67
|
-
else
|
68
|
-
"#{search.klass.to_s.underscore}_search"
|
69
|
-
end
|
69
|
+
return option.to_s if option.present?
|
70
|
+
"#{search.klass.to_s.underscore}_search"
|
70
71
|
end
|
71
72
|
|
72
73
|
def extract_search_and_routing_proxy(search)
|
73
|
-
if search.is_a?
|
74
|
-
|
75
|
-
else
|
76
|
-
[search, nil]
|
77
|
-
end
|
74
|
+
return [search[1], search[0]] if search.is_a?(Array)
|
75
|
+
[search, nil]
|
78
76
|
end
|
79
77
|
|
80
78
|
def url(routing_proxy, options_for_url)
|
@@ -88,20 +86,21 @@ module Ransack
|
|
88
86
|
class SortLink
|
89
87
|
def initialize(search, attribute, args, params)
|
90
88
|
@search = search
|
91
|
-
@params = params
|
89
|
+
@params = parameters_hash(params)
|
92
90
|
@field = attribute.to_s
|
93
91
|
@sort_fields = extract_sort_fields_and_mutate_args!(args).compact
|
94
92
|
@current_dir = existing_sort_direction
|
95
93
|
@label_text = extract_label_and_mutate_args!(args)
|
96
94
|
@options = extract_options_and_mutate_args!(args)
|
97
|
-
@hide_indicator = @options.delete
|
95
|
+
@hide_indicator = @options.delete(:hide_indicator) ||
|
96
|
+
Ransack.options[:hide_sort_order_indicators]
|
98
97
|
@default_order = @options.delete :default_order
|
99
98
|
end
|
100
99
|
|
101
100
|
def name
|
102
101
|
[ERB::Util.h(@label_text), order_indicator]
|
103
102
|
.compact
|
104
|
-
.join(
|
103
|
+
.join(' '.freeze)
|
105
104
|
.html_safe
|
106
105
|
end
|
107
106
|
|
@@ -114,35 +113,34 @@ module Ransack
|
|
114
113
|
def html_options(args)
|
115
114
|
html_options = extract_options_and_mutate_args!(args)
|
116
115
|
html_options.merge(
|
117
|
-
class: [[
|
118
|
-
.compact.join(
|
116
|
+
class: [['sort_link'.freeze, @current_dir], html_options[:class]]
|
117
|
+
.compact.join(' '.freeze)
|
119
118
|
)
|
120
119
|
end
|
121
120
|
|
122
121
|
private
|
123
122
|
|
124
|
-
def
|
125
|
-
if
|
126
|
-
|
123
|
+
def parameters_hash(params)
|
124
|
+
if ::ActiveRecord::VERSION::MAJOR == 5 && params.respond_to?(:to_unsafe_h)
|
125
|
+
params.to_unsafe_h
|
127
126
|
else
|
128
|
-
|
127
|
+
params
|
129
128
|
end
|
130
129
|
end
|
131
130
|
|
131
|
+
def extract_sort_fields_and_mutate_args!(args)
|
132
|
+
return args.shift if args[0].is_a?(Array)
|
133
|
+
[@field]
|
134
|
+
end
|
135
|
+
|
132
136
|
def extract_label_and_mutate_args!(args)
|
133
|
-
if args.
|
134
|
-
|
135
|
-
else
|
136
|
-
Translate.attribute(@field, context: @search.context)
|
137
|
-
end
|
137
|
+
return args.shift if args[0].is_a?(String)
|
138
|
+
Translate.attribute(@field, context: @search.context)
|
138
139
|
end
|
139
140
|
|
140
141
|
def extract_options_and_mutate_args!(args)
|
141
|
-
if args.
|
142
|
-
|
143
|
-
else
|
144
|
-
{}
|
145
|
-
end
|
142
|
+
return args.shift.with_indifferent_access if args[0].is_a?(Hash)
|
143
|
+
{}
|
146
144
|
end
|
147
145
|
|
148
146
|
def search_and_sort_params
|
@@ -155,11 +153,8 @@ module Ransack
|
|
155
153
|
|
156
154
|
def sort_params
|
157
155
|
sort_array = recursive_sort_params_build(@sort_fields)
|
158
|
-
if sort_array.
|
159
|
-
|
160
|
-
else
|
161
|
-
sort_array
|
162
|
-
end
|
156
|
+
return sort_array[0] if sort_array.length == 1
|
157
|
+
sort_array
|
163
158
|
end
|
164
159
|
|
165
160
|
def recursive_sort_params_build(fields)
|
@@ -179,52 +174,38 @@ module Ransack
|
|
179
174
|
if sort_dir = existing_sort_direction(attr_name)
|
180
175
|
direction_text(sort_dir)
|
181
176
|
else
|
182
|
-
default_sort_order(attr_name) ||
|
177
|
+
default_sort_order(attr_name) || 'asc'.freeze
|
183
178
|
end
|
184
179
|
end
|
185
180
|
|
186
|
-
def existing_sort_direction(
|
187
|
-
|
188
|
-
|
189
|
-
end
|
181
|
+
def existing_sort_direction(f = @field)
|
182
|
+
return unless sort = @search.sorts.detect { |s| s && s.name == f }
|
183
|
+
sort.dir
|
190
184
|
end
|
191
185
|
|
192
186
|
def default_sort_order(attr_name)
|
193
|
-
if Hash === @default_order
|
194
|
-
|
195
|
-
else
|
196
|
-
@default_order
|
197
|
-
end
|
187
|
+
return @default_order[attr_name] if Hash === @default_order
|
188
|
+
@default_order
|
198
189
|
end
|
199
190
|
|
200
191
|
def order_indicator
|
201
|
-
if @hide_indicator || no_sort_direction_specified?
|
202
|
-
|
203
|
-
else
|
204
|
-
direction_arrow
|
205
|
-
end
|
192
|
+
return if @hide_indicator || no_sort_direction_specified?
|
193
|
+
direction_arrow
|
206
194
|
end
|
207
195
|
|
208
196
|
def no_sort_direction_specified?(dir = @current_dir)
|
209
|
-
!
|
197
|
+
!['asc'.freeze, 'desc'.freeze].freeze.include?(dir)
|
210
198
|
end
|
211
199
|
|
212
200
|
def direction_arrow
|
213
|
-
if @current_dir ==
|
214
|
-
|
215
|
-
else
|
216
|
-
Constants::ASC_ARROW
|
217
|
-
end
|
201
|
+
return Constants::DESC_ARROW if @current_dir == 'desc'.freeze
|
202
|
+
Constants::ASC_ARROW
|
218
203
|
end
|
219
204
|
|
220
205
|
def direction_text(dir)
|
221
|
-
if dir ==
|
222
|
-
|
223
|
-
else
|
224
|
-
Constants::DESC
|
225
|
-
end
|
206
|
+
return 'asc'.freeze if dir == 'desc'.freeze
|
207
|
+
'desc'.freeze
|
226
208
|
end
|
227
|
-
|
228
209
|
end
|
229
210
|
end
|
230
211
|
end
|