52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# File 'lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb', line 52
def craft_filter_query(nodetree, for_model:)
result = _compute_joins_and_conditions_data(nodetree, model: for_model, parent_reflection: nil)
return @initial_query if result[:conditions].empty?
root_parent_group = result[:conditions].first[:node_object].parent_group || result[:conditions].first[:node_object]
root_parent_group = root_parent_group.parent_group until root_parent_group.parent_group.nil?
query_with_joins = result[:associations_hash].empty? ? @initial_query : @initial_query.left_outer_joins(result[:associations_hash])
apply_single_condition = proc do |condition, associated_query|
colo = condition[:model].columns_hash[condition[:name].to_s]
column_prefix = condition[:column_prefix]
association_key_column = \
if (ref = condition[:parent_reflection])
target_model = ref.klass
target_model.columns_hash[ref.association_primary_key]
end
associated_query = associated_query.references(self.class.build_reference_value(column_prefix, query: associated_query)) unless for_model.table_name == column_prefix
self.class.add_clause(
query: associated_query,
column_prefix: column_prefix,
column_object: colo,
op: condition[:op],
value: condition[:value],
fuzzy: condition[:fuzzy],
association_key_column: association_key_column
)
end
if @active_record_version < Gem::Version.new('6')
if root_parent_group.is_a?(FilteringParams::Condition)
apply_single_condition.call(result[:conditions].first, query_with_joins)
elsif root_parent_group.items.all? { |i| i.is_a?(FilteringParams::Condition) }
if root_parent_group.type == :and
result[:conditions].reverse.inject(query_with_joins) do |accum, condition|
apply_single_condition.call(condition, accum)
end
else
cond1, *rest = result[:conditions].reverse
start_query = apply_single_condition.call(cond1, query_with_joins)
rest.inject(start_query) do |accum, condition|
accum.or(apply_single_condition.call(condition, query_with_joins))
end
end
else
raise 'Mixing AND and OR conditions is not supported for ActiveRecord <6.'
end
else
_depth_first_traversal(
root_query: query_with_joins,
root_node: root_parent_group,
conditions: result[:conditions],
&apply_single_condition
)
end
end
|