Class: Marty::BaseRule
- Inherits:
-
Base
show all
- Defined in:
- app/models/marty/base_rule.rb
Class Method Summary
collapse
Instance Method Summary
collapse
Methods inherited from Base
get_final_attrs, get_struct_attrs, make_hash, make_openstruct, mcfly_pt
joins, old_joins
Class Method Details
.get_matches_(_pt, attrs, params) ⇒ Object
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
|
# File 'app/models/marty/base_rule.rb', line 142
def get_matches_(_pt, attrs, params)
q = select('DISTINCT ON (name) *').where(attrs)
h = guard_info
params.each do |k, vraw|
use_k = (h[k] && k) ||
(h[k + '_array'] && k + '_array') ||
(h[k + '_range'] && k + '_range')
next unless use_k
param_guard_info = h[use_k]
multi = param_guard_info[:multi]
type = param_guard_info[:type]
with_not = param_guard_info.fetch(:allow_not, true)
filts = [vraw].flatten.map do |v|
qstr = get_subq('simple_guards', use_k, multi, type, v)
end.join(' OR ')
condition = if with_not
"CASE
WHEN (simple_guards_options->'#{use_k}'->>'not')::boolean
THEN simple_guards->'#{use_k}' IS NULL OR NOT #{filts}
ELSE simple_guards->'#{use_k}' IS NULL OR #{filts}
END
"
else
"simple_guards->'#{use_k}' IS NULL OR #{filts}"
end
q = q.where(condition)
end
q.order(:name)
end
|
.get_subq(field, subfield, multi, type, vraw) ⇒ Object
129
130
131
132
133
134
135
136
137
138
139
140
|
# File 'app/models/marty/base_rule.rb', line 129
def get_subq(field, subfield, multi, type, vraw)
arrow = multi || ![:range, :string, :date, :datetime].include?(type) ?
'->' : '->>'
op = multi || type == :range ? '@>' : '='
value0 = [:string, :date, :datetime].include?(type) ?
ActiveRecord::Base.connection.quote(vraw) :
type == :range ? vraw.to_f :
"'#{vraw}'::jsonb"
value = multi ? %Q('["%s"]') % value0[1..-2] : value0
fieldcast = type == :range ? '::numrange' : ''
"(#{field}#{arrow}'#{subfield}')#{fieldcast} #{op} #{value}"
end
|
.guard_info ⇒ Object
5
6
7
|
# File 'app/models/marty/base_rule.rb', line 5
def self.guard_info
{}
end
|
Instance Method Details
#check(name, h) ⇒ Object
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
# File 'app/models/marty/base_rule.rb', line 25
def check(name, h)
multi, type, enum, values, req = h.values_at(:multi, :type, :enum, :values,
:required)
ns = "'#{name}'"
expmulti = multi ? 'multi' : 'single'
errtype = :guards
v = simple_guards[name]
type ||= :string
return errors[errtype] << "- Required field #{ns} is missing" if
v.blank? && req
return if v.blank?
gotmulti = v.is_a?(Array) ? 'multi' : 'single'
return errors[errtype] << "- Wrong arity for #{ns} (expected #{expmulti} "\
"got #{gotmulti})" if expmulti != gotmulti
vs = [v].flatten.to_set
vs.each do |vv|
return errors[errtype] << "- Wrong type for #{ns}" unless
gettypes(vv).member?(type)
end
return unless enum || values
vals = enum&.values || values.to_set
bad = (vs - vals)
p = bad.count > 1 ? 's' : ''
return errors[errtype] <<
%Q(- Bad value#{p} '#{bad.to_a.join("', '")}' for #{ns}) if bad.present?
end
|
#chkrange(v) ⇒ Object
9
10
11
|
# File 'app/models/marty/base_rule.rb', line 9
def chkrange(v)
v.match(/\A(\[|\()([0-9\.-]*),([0-9\.-]*)(\]|\))\z/)
end
|
#gettypes(v) ⇒ Object
13
14
15
16
17
18
19
20
21
22
23
|
# File 'app/models/marty/base_rule.rb', line 13
def gettypes(v)
types = []
types << :string if v.is_a?(String)
types += [:int, :integer] if Integer(v) rescue nil
types << :float if Float(v) rescue nil
types << :date if Date.parse(v) rescue nil
types << :datetime if DateTime.parse(v) rescue nil
types << :range if chkrange(v) rescue nil
types << :boolean if [true, false, 'True', 'False'].include?(v)
types
end
|
#validate ⇒ Object
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# File 'app/models/marty/base_rule.rb', line 55
def validate
self.class.guard_info.each { |name, h| check(name, h) }
grids.each do |vn, gn|
return errors[:grids] << "- Bad grid name '#{gn}' for '#{vn}'" unless
gn.blank? || Marty::DataGrid.lookup('infinity', gn)
end
cg_err = computed_guards.delete('~~ERROR~~')
errors[:computed] <<
"- Error in rule '#{name}' field 'computed_guards': #{cg_err.capitalize}" if cg_err
res_err = results.delete('~~ERROR~~')
errors[:computed] <<
"- Error in rule '#{name}' field 'results': #{res_err.capitalize}" if res_err
end
|