Class: Refine::Filter
Defined Under Namespace
Modules: Internationalized
Class Attribute Summary collapse
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from Inspector
#has_duplicate_conditions?, #uses_and?, #uses_condition, #uses_condition_at_least, #uses_negative_clause?, #uses_or?
Methods included from Stabilize
#automatic_stable_id_generator, #create_stable_id, #make_stable_id_generator, #to_optional_stable_id
#add_pending_joins_relationship_subquery, #add_pending_relationship_subquery, #allow_pending_relationship_to_collapse, #commit_pending_relationship_subqueries, #commit_subset, #get_current_relationship, #get_pending_relationship_instance, #get_pending_relationship_item, #get_pending_relationship_subquery, #pending_relationship_subqueries, #pending_relationship_subquery_depth, #relationship_supports_collapsing, #release_pending_relationship, #set_pending_relationship, #set_pending_relationship_subquery_wrapper, #use_multiple_databases?
Constructor Details
#initialize(blueprint = nil, query_scope = nil) ⇒ Filter
Returns a new instance of Filter.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# File 'app/models/refine/filter.rb', line 39
def initialize(blueprint = nil, query_scope = nil)
run_callbacks :initialize do
if blueprint.is_a? Blueprints::Blueprint
blueprint = blueprint.to_array
end
@initial_query = query_scope
@blueprint = blueprint
@relation = initial_query
@immediately_commit_pending_relationship_subqueries = false
@@default_stabilizer = Refine::Stabilizers::UrlEncodedStabilizer
end
end
|
Class Attribute Details
.default_condition_id ⇒ Object
Returns the value of attribute default_condition_id.
35
36
37
|
# File 'app/models/refine/filter.rb', line 35
def default_condition_id
@default_condition_id
end
|
Instance Attribute Details
#blueprint ⇒ Object
Returns the value of attribute blueprint.
24
25
26
|
# File 'app/models/refine/filter.rb', line 24
def blueprint
@blueprint
end
|
#initial_query ⇒ Object
Returns the value of attribute initial_query.
24
25
26
|
# File 'app/models/refine/filter.rb', line 24
def initial_query
@initial_query
end
|
Class Method Details
.default_stable_id_generator(klass) ⇒ Object
298
299
300
301
302
303
304
|
# File 'app/models/refine/filter.rb', line 298
def self.default_stable_id_generator(klass)
if klass.method_defined?(:to_stable_id) && klass.method_defined?(:from_stable_id)
@@default_stabilizer = klass
else
raise ArgumentError.new('Given class doesn\'t implement to_stable_id and from_stable_id!')
end
end
|
.from_state(state, initial_query = nil) ⇒ Object
293
294
295
296
|
# File 'app/models/refine/filter.rb', line 293
def self.from_state(state, initial_query = nil)
klass = state[:type].constantize
filter = klass.new(state[:blueprint], initial_query)
end
|
.model ⇒ Object
17
18
19
|
# File 'app/models/refine/filter.rb', line 17
def self.model
@model ||= model_name.constantize
end
|
.model_name ⇒ Object
13
14
15
|
# File 'app/models/refine/filter.rb', line 13
def self.model_name
name.sub(/(::)?Filter$/, "").singularize
end
|
Instance Method Details
#add_nodes_to_query(subquery:, nodes:, query_method:) ⇒ Object
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
# File 'app/models/refine/filter.rb', line 115
def add_nodes_to_query(subquery:, nodes:, query_method:)
if subquery.present? && nodes.present?
subquery = if query_method == "and"
subquery.send(query_method, group(nodes))
else
Arel::Nodes::Or.new(subquery, group(nodes))
end
elsif subquery.present? && nodes.blank?
subquery
elsif subquery.blank? && !nodes.nil?
subquery = group(nodes)
end
subquery
end
|
#apply_condition(criterion) ⇒ Object
221
222
223
224
225
226
227
228
229
230
|
# File 'app/models/refine/filter.rb', line 221
def apply_condition(criterion)
begin
condition = get_condition_for_criterion(criterion)
get_condition_for_criterion(criterion)&.apply(criterion[:input], table, initial_query, false, nil)
rescue Refine::Conditions::Errors::ConditionClauseError => e
e.errors.each do |error|
errors.add(:base, error.full_message, criterion_uid: criterion[:uid])
end
end
end
|
#automatically_stabilize? ⇒ Boolean
74
75
76
|
# File 'app/models/refine/filter.rb', line 74
def automatically_stabilize?
true
end
|
#blueprint_criteria ⇒ Object
310
311
312
|
# File 'app/models/refine/filter.rb', line 310
def blueprint_criteria
blueprint&.filter { |node| node.is_a?(Hash) && node[:type] == 'criterion' }.to_a
end
|
#clear_blueprint! ⇒ Object
330
331
332
|
# File 'app/models/refine/filter.rb', line 330
def clear_blueprint!
@blueprint = []
end
|
#conditions_to_array ⇒ Object
256
257
258
259
260
|
# File 'app/models/refine/filter.rb', line 256
def conditions_to_array
return nil unless conditions
conditions.map { |condition| instantiate_condition(condition) }.map(&:to_array)
end
|
#configuration ⇒ Object
246
247
248
249
250
251
252
253
254
|
# File 'app/models/refine/filter.rb', line 246
def configuration
{
type: "Refine",
class_name: self.class.name,
blueprint: @blueprint,
conditions: conditions_to_array,
stable_id: to_optional_stable_id
}
end
|
#criteria_limit_exceeded? ⇒ Boolean
314
315
316
|
# File 'app/models/refine/filter.rb', line 314
def criteria_limit_exceeded?
criteria_limit_set? && blueprint_criteria.length > criteria_limit
end
|
#criteria_limit_reached? ⇒ Boolean
318
319
320
|
# File 'app/models/refine/filter.rb', line 318
def criteria_limit_reached?
criteria_limit_set? && blueprint_criteria.length >= criteria_limit
end
|
#criteria_limit_set? ⇒ Boolean
322
323
324
|
# File 'app/models/refine/filter.rb', line 322
def criteria_limit_set?
criteria_limit.to_i.positive?
end
|
#fast_forward(index, modified_blueprint, depth) ⇒ Object
208
209
210
211
212
213
214
215
|
# File 'app/models/refine/filter.rb', line 208
def fast_forward(index, modified_blueprint, depth)
fast_forward_index = (index..modified_blueprint.length - 1).each do |cursor|
break cursor if modified_blueprint[cursor][:depth] <= depth
end
(fast_forward_index.is_a? Integer) ? fast_forward_index : modified_blueprint.length - 1
end
|
#get_complex_query ⇒ Object
107
108
109
110
111
112
113
|
# File 'app/models/refine/filter.rb', line 107
def get_complex_query
if blueprint.present?
@relation.where(group(make_sub_query(blueprint)))
else
@relation
end
end
|
#get_condition_for_criterion(criterion) ⇒ Object
232
233
234
235
236
237
238
239
240
241
242
243
244
|
# File 'app/models/refine/filter.rb', line 232
def get_condition_for_criterion(criterion)
returned_object = conditions.find { |condition| condition.id == criterion[:condition_id] }
if returned_object.nil?
errors.add(:filter, "The condition ID #{criterion[:condition_id]} was not found")
else
instantiate_condition(returned_object)
end
returned_object.dup
end
|
#get_query ⇒ Object
92
93
94
95
96
97
98
99
|
# File 'app/models/refine/filter.rb', line 92
def get_query
raise "Initial query must exist" if initial_query.nil?
if self.class.included_modules.include?(Refine::FlatQueryTools) && can_use_flat_query?
get_flat_query
else
get_complex_query
end
end
|
#get_query! ⇒ Object
101
102
103
104
105
|
# File 'app/models/refine/filter.rb', line 101
def get_query!
result = get_query
raise Refine::InvalidFilterError.new(filter: self) unless errors.none?
result
end
|
#group(nodes) ⇒ Object
217
218
219
|
# File 'app/models/refine/filter.rb', line 217
def group(nodes)
Arel::Nodes::Grouping.new(nodes)
end
|
#has_category_ordering? ⇒ Boolean
326
327
328
|
# File 'app/models/refine/filter.rb', line 326
def has_category_ordering?
respond_to?(:category_order) && category_order.is_a?(Array) && category_order.any?
end
|
#human_readable_criterions ⇒ Object
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
# File 'app/models/refine/filter.rb', line 54
def human_readable_criterions
output = []
if blueprint.present?
blueprint.each do |criterion|
if criterion[:type] == "conjunction"
output << criterion[:word]
else
condition = get_condition_for_criterion(criterion)
text = condition.human_readable(criterion[:input])
if condition.has_date_refinement?
date_refinement_condition = condition.has_date_refinement?.call
text += date_refinement_condition.human_readable(criterion[:input][:date_refinement])
end
output << text
end
end
end
output
end
|
#instantiate_condition(condition) ⇒ Object
262
263
264
265
266
|
# File 'app/models/refine/filter.rb', line 262
def instantiate_condition(condition)
condition.set_filter(self)
translate_display(condition)
condition
end
|
#instantiated_conditions ⇒ Object
Set filter object on condition and sort alphabetically
269
270
271
272
273
|
# File 'app/models/refine/filter.rb', line 269
def instantiated_conditions
conditions
.map { |c| instantiate_condition(c.dup) }
.sort_by { |c| c.display.to_s.downcase }
end
|
#make_sub_query(modified_blueprint, depth = 0, subquery = nil) ⇒ Object
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
# File 'app/models/refine/filter.rb', line 136
def make_sub_query(modified_blueprint, depth = 0, subquery = nil)
index = 0
while index < modified_blueprint.length
criterion = modified_blueprint[index]
break if criterion[:depth] < depth
if criterion[:type] == "conjunction"
index += 1
next
end
query_method = if index == 0
"and"
else
modified_blueprint[index - 1][:word] == "and" ? "and" : "or"
end
if criterion[:depth] > depth
new_depth_array = modified_blueprint[index..-1]
recursive_nodes = make_sub_query(new_depth_array, depth + 1)
subquery = add_nodes_to_query(subquery: subquery, nodes: recursive_nodes, query_method: query_method)
index = fast_forward(index, modified_blueprint, depth) + 1
next
end
@immediately_commit_pending_relationship_subqueries = if modified_blueprint.select { |item| (item[:type] == "conjunction" && item[:word] == "or" && item[:depth] == depth) }.present?
true
else
false
end
nodes_to_apply = apply_condition(criterion)
if errors.any?
index += 1
next
end
subquery = add_nodes_to_query(subquery: subquery, nodes: nodes_to_apply, query_method: query_method)
if @immediately_commit_pending_relationship_subqueries.present?
committed_nodes_from_pending = commit_pending_relationship_subqueries
subquery = add_nodes_to_query(subquery: subquery, nodes: committed_nodes_from_pending, query_method: query_method)
end
index += 1
end
unless errors.any?
final_depth_nodes = commit_pending_relationship_subqueries
add_nodes_to_query(subquery: subquery, nodes: final_depth_nodes, query_method: query_method)
end
end
|
#model ⇒ Object
e.g. ContactsFilter -> Contact
79
80
81
|
# File 'app/models/refine/filter.rb', line 79
def model
initial_query&.model || self.class.model
end
|
#state ⇒ Object
282
283
284
285
286
287
|
# File 'app/models/refine/filter.rb', line 282
def state
{
type: type,
blueprint: blueprint
}.to_json
end
|
#table ⇒ Object
83
84
85
|
# File 'app/models/refine/filter.rb', line 83
def table
model.arel_table
end
|
#to_stable_id ⇒ Object
306
307
308
|
# File 'app/models/refine/filter.rb', line 306
def to_stable_id
Refine::Rails.configuration.stabilizer_classes[:url].new.to_stable_id(filter: self)
end
|
#translate_display(condition) ⇒ Object
275
276
277
278
279
280
|
# File 'app/models/refine/filter.rb', line 275
def translate_display(condition)
label_fallback = {default: condition.id.humanize(keep_id_suffix: true).titleize}
condition.display = condition.display || I18n.t(".filter.conditions.#{condition.id}.label", default: I18n.t(".fields.#{condition.id}.label", **label_fallback))
end
|
#type ⇒ Object
289
290
291
|
# File 'app/models/refine/filter.rb', line 289
def type
self.class.name
end
|
#valid_query? ⇒ Boolean
87
88
89
90
|
# File 'app/models/refine/filter.rb', line 87
def valid_query?
get_query
errors.none?
end
|