ransack 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -29,8 +29,14 @@ module Ransack
29
29
  relation = relation.except(:order)
30
30
  .reorder(viz.accept(search.sorts))
31
31
  end
32
- opts[:distinct] ?
33
- relation.select("DISTINCT #{@klass.quoted_table_name}.*") : relation
32
+ if opts[:distinct]
33
+ relation.select(
34
+ Ransack::Constants::DISTINCT + @klass.quoted_table_name +
35
+ '.*'.freeze
36
+ )
37
+ else
38
+ relation
39
+ end
34
40
  end
35
41
 
36
42
  def attribute_method?(str, klass = @klass)
@@ -44,11 +50,12 @@ module Ransack
44
50
  while !found_assoc && remainder.unshift(segments.pop) &&
45
51
  segments.size > 0 do
46
52
  assoc, poly_class = unpolymorphize_association(
47
- segments.join('_')
53
+ segments.join(Ransack::Constants::UNDERSCORE)
48
54
  )
49
55
  if found_assoc = get_association(assoc, klass)
50
56
  exists = attribute_method?(
51
- remainder.join('_'), poly_class || found_assoc.klass
57
+ remainder.join(Ransack::Constants::UNDERSCORE),
58
+ poly_class || found_assoc.klass
52
59
  )
53
60
  end
54
61
  end
@@ -96,13 +103,15 @@ module Ransack
96
103
  found_assoc = nil
97
104
  while remainder.unshift(segments.pop) && segments.size > 0 &&
98
105
  !found_assoc do
99
- assoc, klass = unpolymorphize_association(segments.join('_'))
106
+ assoc, klass = unpolymorphize_association(
107
+ segments.join(Ransack::Constants::UNDERSCORE)
108
+ )
100
109
  if found_assoc = get_association(assoc, parent)
101
110
  join = build_or_find_association(
102
111
  found_assoc.name, parent, klass
103
112
  )
104
113
  parent, attr_name = get_parent_and_attribute_name(
105
- remainder.join('_'), join
114
+ remainder.join(Ransack::Constants::UNDERSCORE), join
106
115
  )
107
116
  end
108
117
  end
@@ -128,24 +137,31 @@ module Ransack
128
137
  buckets = relation.joins_values.group_by do |join|
129
138
  case join
130
139
  when String
131
- 'string_join'
140
+ Ransack::Constants::STRING_JOIN
132
141
  when Hash, Symbol, Array
133
- 'association_join'
142
+ Ransack::Constants::ASSOCIATION_JOIN
134
143
  when ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation
135
- 'stashed_join'
144
+ Ransack::Constants::STASHED_JOIN
136
145
  when Arel::Nodes::Join
137
- 'join_node'
146
+ Ransack::Constants::JOIN_NODE
138
147
  else
139
148
  raise 'unknown class: %s' % join.class.name
140
149
  end
141
150
  end
142
151
 
143
- association_joins = buckets['association_join'] || []
144
- stashed_association_joins = buckets['stashed_join'] || []
145
- join_nodes = buckets['join_node'] || []
146
- string_joins = (buckets['string_join'] || [])
147
- .map { |x| x.strip }
148
- .uniq
152
+ association_joins =
153
+ buckets[Ransack::Constants::ASSOCIATION_JOIN] || []
154
+
155
+ stashed_association_joins =
156
+ buckets[Ransack::Constants::STASHED_JOIN] || []
157
+
158
+ join_nodes =
159
+ buckets[Ransack::Constants::JOIN_NODE] || []
160
+
161
+ string_joins =
162
+ (buckets[Ransack::Constants::STRING_JOIN] || [])
163
+ .map { |x| x.strip }
164
+ .uniq
149
165
 
150
166
  join_list = relation.send :custom_join_sql, (string_joins + join_nodes)
151
167
 
@@ -28,9 +28,14 @@ module Ransack
28
28
  relation = relation.except(:order)
29
29
  .reorder(viz.accept(search.sorts))
30
30
  end
31
- opts[:distinct] ?
32
- relation.select("DISTINCT #{@klass.quoted_table_name}.*") :
31
+ if opts[:distinct]
32
+ relation.select(
33
+ Ransack::Constants::DISTINCT + @klass.quoted_table_name +
34
+ '.*'.freeze
35
+ )
36
+ else
33
37
  relation
38
+ end
34
39
  end
35
40
 
36
41
  def attribute_method?(str, klass = @klass)
@@ -44,11 +49,12 @@ module Ransack
44
49
  while !found_assoc && remainder.unshift(segments.pop) &&
45
50
  segments.size > 0 do
46
51
  assoc, poly_class = unpolymorphize_association(
47
- segments.join('_')
52
+ segments.join(Ransack::Constants::UNDERSCORE)
48
53
  )
49
54
  if found_assoc = get_association(assoc, klass)
50
55
  exists = attribute_method?(
51
- remainder.join('_'), poly_class || found_assoc.klass
56
+ remainder.join(Ransack::Constants::UNDERSCORE),
57
+ poly_class || found_assoc.klass
52
58
  )
53
59
  end
54
60
  end
@@ -109,13 +115,15 @@ module Ransack
109
115
  found_assoc = nil
110
116
  while remainder.unshift(segments.pop) && segments.size > 0 &&
111
117
  !found_assoc do
112
- assoc, klass = unpolymorphize_association(segments.join('_'))
118
+ assoc, klass = unpolymorphize_association(
119
+ segments.join(Ransack::Constants::UNDERSCORE)
120
+ )
113
121
  if found_assoc = get_association(assoc, parent)
114
122
  join = build_or_find_association(
115
123
  found_assoc.name, parent, klass
116
124
  )
117
125
  parent, attr_name = get_parent_and_attribute_name(
118
- remainder.join('_'), join
126
+ remainder.join(Ransack::Constants::UNDERSCORE), join
119
127
  )
120
128
  end
121
129
  end
@@ -142,24 +150,31 @@ module Ransack
142
150
  buckets = relation.joins_values.group_by do |join|
143
151
  case join
144
152
  when String
145
- 'string_join'
153
+ Ransack::Constants::STRING_JOIN
146
154
  when Hash, Symbol, Array
147
- 'association_join'
155
+ Ransack::Constants::ASSOCIATION_JOIN
148
156
  when ::ActiveRecord::Associations::JoinDependency::JoinAssociation
149
- 'stashed_join'
157
+ Ransack::Constants::STASHED_JOIN
150
158
  when Arel::Nodes::Join
151
- 'join_node'
159
+ Ransack::Constants::JOIN_NODE
152
160
  else
153
161
  raise 'unknown class: %s' % join.class.name
154
162
  end
155
163
  end
156
164
 
157
- association_joins = buckets['association_join'] || []
158
- stashed_association_joins = buckets['stashed_join'] || []
159
- join_nodes = buckets['join_node'] || []
160
- string_joins = (buckets['string_join'] || [])
161
- .map { |x| x.strip }
162
- .uniq
165
+ association_joins =
166
+ buckets[Ransack::Constants::ASSOCIATION_JOIN] || []
167
+
168
+ stashed_association_joins =
169
+ buckets[Ransack::Constants::STASHED_JOIN] || []
170
+
171
+ join_nodes =
172
+ buckets[Ransack::Constants::JOIN_NODE] || []
173
+
174
+ string_joins =
175
+ (buckets[Ransack::Constants::STRING_JOIN] || [])
176
+ .map { |x| x.strip }
177
+ .uniq
163
178
 
164
179
  join_list = relation.send :custom_join_ast,
165
180
  relation.table.from(relation.table), string_joins
@@ -34,8 +34,7 @@ module Ransack
34
34
  viz = Visitor.new
35
35
  relation = @object.where(viz.accept(search.base))
36
36
  if search.sorts.any?
37
- relation = relation.except(:order)
38
- .reorder(viz.accept(search.sorts))
37
+ relation = relation.except(:order).reorder(viz.accept(search.sorts))
39
38
  end
40
39
  opts[:distinct] ? relation.distinct : relation
41
40
  end
@@ -47,15 +46,16 @@ module Ransack
47
46
  elsif (segments = str.split(/_/)).size > 1
48
47
  remainder = []
49
48
  found_assoc = nil
50
- while !found_assoc && remainder.unshift(
51
- segments.pop) && segments.size > 0 do
49
+ while !found_assoc && remainder.unshift(segments.pop) &&
50
+ segments.size > 0 do
52
51
  assoc, poly_class = unpolymorphize_association(
53
- segments.join('_')
52
+ segments.join(Ransack::Constants::UNDERSCORE)
54
53
  )
55
54
  if found_assoc = get_association(assoc, klass)
56
- exists = attribute_method?(remainder.join('_'),
55
+ exists = attribute_method?(
56
+ remainder.join(Ransack::Constants::UNDERSCORE),
57
57
  poly_class || found_assoc.klass
58
- )
58
+ )
59
59
  end
60
60
  end
61
61
  end
@@ -78,7 +78,7 @@ module Ransack
78
78
  end
79
79
  end
80
80
 
81
- if ::ActiveRecord::VERSION::STRING >= '4.1'
81
+ if ::ActiveRecord::VERSION::STRING >= '4.1'.freeze
82
82
 
83
83
  def join_associations
84
84
  raise NotImplementedError,
@@ -133,16 +133,20 @@ module Ransack
133
133
 
134
134
  if ransackable_attribute?(str, klassify(parent))
135
135
  attr_name = str
136
- elsif (segments = str.split(/_/)).size > 1
136
+ elsif (segments = str.split(Ransack::Constants::UNDERSCORE)).size > 1
137
137
  remainder = []
138
138
  found_assoc = nil
139
- while remainder.unshift(
140
- segments.pop) && segments.size > 0 && !found_assoc do
141
- assoc, klass = unpolymorphize_association(segments.join('_'))
139
+ while remainder.unshift(segments.pop) && segments.size > 0 &&
140
+ !found_assoc do
141
+ assoc, klass = unpolymorphize_association(
142
+ segments.join(Ransack::Constants::UNDERSCORE)
143
+ )
142
144
  if found_assoc = get_association(assoc, parent)
143
- join = build_or_find_association(found_assoc.name, parent, klass)
145
+ join = build_or_find_association(
146
+ found_assoc.name, parent, klass
147
+ )
144
148
  parent, attr_name = get_parent_and_attribute_name(
145
- remainder.join('_'), join
149
+ remainder.join(Ransack::Constants::UNDERSCORE), join
146
150
  )
147
151
  end
148
152
  end
@@ -171,27 +175,31 @@ module Ransack
171
175
  buckets = relation.joins_values.group_by do |join|
172
176
  case join
173
177
  when String
174
- 'string_join'
178
+ STRING_JOIN
175
179
  when Hash, Symbol, Array
176
- 'association_join'
180
+ ASSOCIATION_JOIN
177
181
  when JoinDependency, JoinDependency::JoinAssociation
178
- 'stashed_join'
182
+ STASHED_JOIN
179
183
  when Arel::Nodes::Join
180
- 'join_node'
184
+ JOIN_NODE
181
185
  else
182
186
  raise 'unknown class: %s' % join.class.name
183
187
  end
184
188
  end
185
189
 
186
- association_joins = buckets['association_join'] || []
190
+ association_joins =
191
+ buckets[Ransack::Constants::ASSOCIATION_JOIN] || []
187
192
 
188
- stashed_association_joins = buckets['stashed_join'] || []
193
+ stashed_association_joins =
194
+ buckets[Ransack::Constants::STASHED_JOIN] || []
189
195
 
190
- join_nodes = buckets['join_node'] || []
196
+ join_nodes =
197
+ buckets[Ransack::Constants::JOIN_NODE] || []
191
198
 
192
- string_joins = (buckets['string_join'] || [])
193
- .map { |x| x.strip }
194
- .uniq
199
+ string_joins =
200
+ (buckets[Ransack::Constants::STRING_JOIN] || [])
201
+ .map { |x| x.strip }
202
+ .uniq
195
203
 
196
204
  join_list = relation.send :custom_join_ast,
197
205
  relation.table.from(relation.table), string_joins
@@ -204,14 +212,14 @@ module Ransack
204
212
  join_dependency.alias_tracker.aliases[join.left.name.downcase] = 1
205
213
  end
206
214
 
207
- if ::ActiveRecord::VERSION::STRING >= '4.1'
215
+ if ::ActiveRecord::VERSION::STRING >= '4.1'.freeze
208
216
  join_dependency
209
217
  else
210
218
  join_dependency.graft(*stashed_association_joins)
211
219
  end
212
220
  end
213
221
 
214
- if ::ActiveRecord::VERSION::STRING >= '4.1'
222
+ if ::ActiveRecord::VERSION::STRING >= '4.1'.freeze
215
223
 
216
224
  def build_or_find_association(name, parent = @base, klass = nil)
217
225
  found_association = @join_dependency.join_root.children
@@ -24,7 +24,7 @@ module Ransack
24
24
 
25
25
  self.predicates[name] = Predicate.new(opts)
26
26
 
27
- ['_any', '_all'].each do |suffix|
27
+ Ransack::Constants::SUFFIXES.each do |suffix|
28
28
  compound_name = name + suffix
29
29
  self.predicates[compound_name] = Predicate.new(
30
30
  opts.merge(
@@ -1,122 +1,157 @@
1
1
  module Ransack
2
2
  module Constants
3
+ ASC = 'asc'.freeze
4
+ DESC = 'desc'.freeze
5
+ ASC_ARROW = '▲'.freeze
6
+ DESC_ARROW = '▼'.freeze
7
+ OR = 'or'.freeze
8
+ AND = 'and'.freeze
9
+ SORT = 'sort'.freeze
10
+ SORT_LINK = 'sort_link'.freeze
11
+ SEARCH = 'search'.freeze
12
+ DEFAULT_SEARCH_KEY = 'q'.freeze
13
+ ATTRIBUTE = 'attribute'.freeze
14
+ DISTINCT = 'DISTINCT '.freeze
15
+ COMBINATOR = 'combinator'.freeze
16
+ SPACE = ' '.freeze
17
+ COMMA_SPACE = ', '.freeze
18
+ UNDERSCORE = '_'.freeze
19
+ NON_BREAKING_SPACE = ' '.freeze
20
+ EMPTY = ''.freeze
21
+ STRING_JOIN = 'string_join'.freeze
22
+ ASSOCIATION_JOIN = 'association_join'.freeze
23
+ STASHED_JOIN = 'stashed_join'.freeze
24
+ JOIN_NODE = 'join_node'.freeze
25
+
3
26
  TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
4
27
  FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
5
28
  BOOLEAN_VALUES = TRUE_VALUES + FALSE_VALUES
6
29
 
7
- AREL_PREDICATES = %w(eq not_eq matches does_not_match lt lteq gt gteq in not_in)
30
+ S_SORTS = %w(s sorts).freeze
31
+ ASC_DESC = %w(asc desc).freeze
32
+ AND_OR = %w(and or).freeze
33
+ IN_NOT_IN = %w(in not_in).freeze
34
+ SUFFIXES = %w(_any _all).freeze
35
+ AREL_PREDICATES = %w(
36
+ eq not_eq matches does_not_match lt lteq gt gteq in not_in
37
+ ).freeze
38
+
39
+ EQ = 'eq'.freeze
40
+ NOT_EQ = 'not_eq'.freeze
41
+ EQ_ANY = 'eq_any'.freeze
42
+ NOT_EQ_ALL = 'not_eq_all'.freeze
8
43
 
9
44
  DERIVED_PREDICATES = [
10
- ['cont', {
11
- :arel_predicate => 'matches',
45
+ ['cont'.freeze, {
46
+ :arel_predicate => 'matches'.freeze,
12
47
  :formatter => proc { |v| "%#{escape_wildcards(v)}%" }
13
48
  }
14
49
  ],
15
- ['i_cont', {
16
- :arel_predicate => 'i_matches',
50
+ ['i_cont'.freeze, {
51
+ :arel_predicate => 'i_matches'.freeze,
17
52
  :formatter => proc { |v| "%#{escape_wildcards(v)}%" }
18
53
  }
19
54
  ],
20
- ['not_cont', {
21
- :arel_predicate => 'does_not_match',
55
+ ['not_cont'.freeze, {
56
+ :arel_predicate => 'does_not_match'.freeze,
22
57
  :formatter => proc { |v| "%#{escape_wildcards(v)}%" }
23
58
  }
24
59
  ],
25
- ['i_not_cont', {
26
- :arel_predicate => 'i_does_not_match',
60
+ ['i_not_cont'.freeze, {
61
+ :arel_predicate => 'i_does_not_match'.freeze,
27
62
  :formatter => proc { |v| "%#{escape_wildcards(v)}%" }
28
63
  }
29
64
  ],
30
- ['start', {
31
- :arel_predicate => 'matches',
65
+ ['start'.freeze, {
66
+ :arel_predicate => 'matches'.freeze,
32
67
  :formatter => proc { |v| "#{escape_wildcards(v)}%" }
33
68
  }
34
69
  ],
35
- ['not_start', {
36
- :arel_predicate => 'does_not_match',
70
+ ['not_start'.freeze, {
71
+ :arel_predicate => 'does_not_match'.freeze,
37
72
  :formatter => proc { |v| "#{escape_wildcards(v)}%" }
38
73
  }
39
74
  ],
40
- ['end', {
41
- :arel_predicate => 'matches',
75
+ ['end'.freeze, {
76
+ :arel_predicate => 'matches'.freeze,
42
77
  :formatter => proc { |v| "%#{escape_wildcards(v)}" }
43
78
  }
44
79
  ],
45
- ['not_end', {
46
- :arel_predicate => 'does_not_match',
80
+ ['not_end'.freeze, {
81
+ :arel_predicate => 'does_not_match'.freeze,
47
82
  :formatter => proc { |v| "%#{escape_wildcards(v)}" }
48
83
  }
49
84
  ],
50
- ['true', {
51
- :arel_predicate => proc { |v| v ? 'eq' : 'not_eq' },
85
+ ['true'.freeze, {
86
+ :arel_predicate => proc { |v| v ? EQ : NOT_EQ },
52
87
  :compounds => false,
53
88
  :type => :boolean,
54
89
  :validator => proc { |v| BOOLEAN_VALUES.include?(v) },
55
90
  :formatter => proc { |v| true }
56
91
  }
57
92
  ],
58
- ['not_true', {
59
- :arel_predicate => proc { |v| v ? 'not_eq' : 'eq' },
93
+ ['not_true'.freeze, {
94
+ :arel_predicate => proc { |v| v ? NOT_EQ : EQ },
60
95
  :compounds => false,
61
96
  :type => :boolean,
62
97
  :validator => proc { |v| BOOLEAN_VALUES.include?(v) },
63
98
  :formatter => proc { |v| true }
64
99
  }
65
100
  ],
66
- ['false', {
67
- :arel_predicate => proc { |v| v ? 'eq' : 'not_eq' },
101
+ ['false'.freeze, {
102
+ :arel_predicate => proc { |v| v ? EQ : NOT_EQ },
68
103
  :compounds => false,
69
104
  :type => :boolean,
70
105
  :validator => proc { |v| BOOLEAN_VALUES.include?(v) },
71
106
  :formatter => proc { |v| false }
72
107
  }
73
108
  ],
74
- ['not_false', {
75
- :arel_predicate => proc { |v| v ? 'not_eq' : 'eq' },
109
+ ['not_false'.freeze, {
110
+ :arel_predicate => proc { |v| v ? NOT_EQ : EQ },
76
111
  :compounds => false,
77
112
  :type => :boolean,
78
113
  :validator => proc { |v| BOOLEAN_VALUES.include?(v) },
79
114
  :formatter => proc { |v| false }
80
115
  }
81
116
  ],
82
- ['present', {
83
- :arel_predicate => proc { |v| v ? 'not_eq_all' : 'eq_any' },
117
+ ['present'.freeze, {
118
+ :arel_predicate => proc { |v| v ? NOT_EQ_ALL : EQ_ANY },
84
119
  :compounds => false,
85
120
  :type => :boolean,
86
121
  :validator => proc { |v| BOOLEAN_VALUES.include?(v) },
87
- :formatter => proc { |v| [nil, ''] }
122
+ :formatter => proc { |v| [nil, Ransack::Constants::EMPTY] }
88
123
  }
89
124
  ],
90
- ['blank', {
91
- :arel_predicate => proc { |v| v ? 'eq_any' : 'not_eq_all' },
125
+ ['blank'.freeze, {
126
+ :arel_predicate => proc { |v| v ? EQ_ANY : NOT_EQ_ALL },
92
127
  :compounds => false,
93
128
  :type => :boolean,
94
129
  :validator => proc { |v| BOOLEAN_VALUES.include?(v) },
95
- :formatter => proc { |v| [nil, ''] }
130
+ :formatter => proc { |v| [nil, Ransack::Constants::EMPTY] }
96
131
  }
97
132
  ],
98
- ['null', {
99
- :arel_predicate => proc { |v| v ? 'eq' : 'not_eq' },
133
+ ['null'.freeze, {
134
+ :arel_predicate => proc { |v| v ? EQ : NOT_EQ },
100
135
  :compounds => false,
101
136
  :type => :boolean,
102
137
  :validator => proc { |v| BOOLEAN_VALUES.include?(v)},
103
138
  :formatter => proc { |v| nil }
104
139
  }
105
140
  ],
106
- ['not_null', {
107
- :arel_predicate => proc { |v| v ? 'not_eq' : 'eq' },
141
+ ['not_null'.freeze, {
142
+ :arel_predicate => proc { |v| v ? NOT_EQ : EQ },
108
143
  :compounds => false,
109
144
  :type => :boolean,
110
145
  :validator => proc { |v| BOOLEAN_VALUES.include?(v) },
111
146
  :formatter => proc { |v| nil } }
112
147
  ]
113
- ]
148
+ ].freeze
114
149
 
115
150
  module_function
116
151
  # replace % \ to \% \\
117
152
  def escape_wildcards(unescaped)
118
153
  case ActiveRecord::Base.connection.adapter_name
119
- when "Mysql2", "PostgreSQL"
154
+ when "Mysql2".freeze, "PostgreSQL".freeze
120
155
  # Necessary for PostgreSQL and MySQL
121
156
  unescaped.to_s.gsub(/([\\|\%|.])/, '\\\\\\1')
122
157
  else