ransack 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|