ransack 1.4.1 → 1.5.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.
@@ -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