reflekt 0.9.9 → 1.0.4
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.
- checksums.yaml +4 -4
- data/lib/Accessor.rb +2 -0
- data/lib/Aggregator.rb +136 -82
- data/lib/Clone.rb +31 -0
- data/lib/Config.rb +8 -1
- data/lib/Control.rb +53 -15
- data/lib/Execution.rb +12 -3
- data/lib/Meta.rb +46 -2
- data/lib/MetaBuilder.rb +32 -4
- data/lib/Reflection.rb +69 -43
- data/lib/Reflekt.rb +68 -45
- data/lib/Rule.rb +11 -1
- data/lib/RuleSet.rb +45 -17
- data/lib/meta/ArrayMeta.rb +3 -2
- data/lib/meta/BooleanMeta.rb +6 -3
- data/lib/meta/FloatMeta.rb +26 -0
- data/lib/meta/IntegerMeta.rb +5 -2
- data/lib/meta/NullMeta.rb +34 -0
- data/lib/meta/StringMeta.rb +5 -2
- data/lib/rules/ArrayRule.rb +14 -1
- data/lib/rules/BooleanRule.rb +9 -4
- data/lib/rules/FloatRule.rb +57 -0
- data/lib/rules/IntegerRule.rb +6 -1
- data/lib/rules/NullRule.rb +36 -0
- data/lib/rules/StringRule.rb +25 -1
- data/lib/web/README.md +3 -3
- data/lib/web/bundle.js +5 -5
- data/lib/web/server.js +45 -49
- metadata +11 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 862841ab79ef50d5b096398525e0f75014b0204184329f8a6b5e010a70927f4f
|
4
|
+
data.tar.gz: 37797b16ae059518507a1e0ec7a0f1e0678cf78da58f3cbd8fafd27bb349d78b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae2247c88853aaba496bba94ab7edfa91dfce613ab42f5e33abe4ab43409c2fddb9eb0888ed71668cc49b860dc323e2a4875ee01b82119ba2576aeb925342b09
|
7
|
+
data.tar.gz: 5f30074666b11dbfc6af40a466e15142c4fd2489d3aa445c6d534c78cf620889768d7934be2077ccdb2690a1ebc860c5770ad9c28a6f31c583b815b9f5a4e8f7
|
data/lib/Accessor.rb
CHANGED
@@ -18,6 +18,7 @@ class Accessor
|
|
18
18
|
attr_accessor :renderer
|
19
19
|
attr_accessor :path
|
20
20
|
attr_accessor :output_path
|
21
|
+
attr_accessor :error
|
21
22
|
|
22
23
|
def initialize()
|
23
24
|
|
@@ -29,6 +30,7 @@ class Accessor
|
|
29
30
|
@renderer = nil
|
30
31
|
@path = nil
|
31
32
|
@output_path = nil
|
33
|
+
@error = false
|
32
34
|
|
33
35
|
end
|
34
36
|
|
data/lib/Aggregator.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
################################################################################
|
2
|
-
# Aggregate
|
3
|
-
# Validate
|
2
|
+
# Aggregate control metadata into rule sets.
|
3
|
+
# Validate reflections against aggregated controls.
|
4
4
|
#
|
5
5
|
# @pattern Singleton
|
6
6
|
#
|
@@ -26,89 +26,30 @@ class Aggregator
|
|
26
26
|
end
|
27
27
|
|
28
28
|
##
|
29
|
-
#
|
29
|
+
# Create aggregated rule sets from control metadata.
|
30
30
|
#
|
31
|
-
# @
|
32
|
-
# @param
|
33
|
-
# @
|
31
|
+
# @stage Called on setup.
|
32
|
+
# @param controls [Array] Controls with metadata.
|
33
|
+
# @TODO Revert string keys to symbols once "Fix Rowdb.get(path)" bug fixed.
|
34
34
|
##
|
35
|
-
def
|
36
|
-
return @rule_sets.dig(klass, method, :inputs)
|
37
|
-
end
|
35
|
+
def train(controls)
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
# @param klass [Symbol]
|
43
|
-
# @param method [Symbol]
|
44
|
-
# @return [RuleSet]
|
45
|
-
##
|
46
|
-
def get_input_rule_set(klass, method, arg_num)
|
47
|
-
@rule_sets.dig(klass, method, :inputs, arg_num)
|
48
|
-
end
|
37
|
+
# On first use there are no previous controls.
|
38
|
+
return if controls.nil?
|
49
39
|
|
50
|
-
|
51
|
-
# Get an aggregated RuleSet for an output.
|
52
|
-
#
|
53
|
-
# @param klass [Symbol]
|
54
|
-
# @param method [Symbol]
|
55
|
-
# @return [RuleSet]
|
56
|
-
##
|
57
|
-
def get_output_rule_set(klass, method)
|
58
|
-
@rule_sets.dig(klass, method, :output)
|
59
|
-
end
|
40
|
+
controls.each do |control|
|
60
41
|
|
61
|
-
|
62
|
-
|
63
|
-
#
|
64
|
-
# @param klass [Symbol]
|
65
|
-
# @param method [Symbol]
|
66
|
-
##
|
67
|
-
def set_input_rule_set(klass, method, arg_num, rule_set)
|
68
|
-
# Set defaults.
|
69
|
-
@rule_sets[klass] = {} unless @rule_sets.key? klass
|
70
|
-
@rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
|
71
|
-
@rule_sets[klass][method][:inputs] = [] unless @rule_sets[klass][method].key? :inputs
|
72
|
-
# Set value.
|
73
|
-
@rule_sets[klass][method][:inputs][arg_num] = rule_set
|
74
|
-
end
|
75
|
-
|
76
|
-
##
|
77
|
-
# Set an aggregated RuleSet for an output.
|
78
|
-
#
|
79
|
-
# @param klass [Symbol]
|
80
|
-
# @param method [Symbol]
|
81
|
-
# @param rule_set [RuleSet]
|
82
|
-
##
|
83
|
-
def set_output_rule_set(klass, method, rule_set)
|
84
|
-
# Set defaults.
|
85
|
-
@rule_sets[klass] = {} unless @rule_sets.key? klass
|
86
|
-
@rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
|
87
|
-
# Set value.
|
88
|
-
@rule_sets[klass][method][:output] = rule_set
|
89
|
-
end
|
90
|
-
|
91
|
-
##
|
92
|
-
# Create aggregated rule sets from reflection metadata.
|
93
|
-
#
|
94
|
-
# @param reflections [Array] Controls with metadata.
|
95
|
-
##
|
96
|
-
def train(reflections)
|
97
|
-
|
98
|
-
# On first use there are no previous reflections.
|
99
|
-
return if reflections.nil?
|
100
|
-
|
101
|
-
reflections.each do |reflection|
|
102
|
-
|
103
|
-
klass = reflection[:class]
|
104
|
-
method = reflection[:method]
|
42
|
+
klass = control["class"].to_sym
|
43
|
+
method = control["method"].to_sym
|
105
44
|
|
106
45
|
##
|
107
46
|
# INPUT
|
108
47
|
##
|
109
48
|
|
110
|
-
unless
|
111
|
-
|
49
|
+
unless control["inputs"].nil?
|
50
|
+
control["inputs"].each_with_index do |meta, arg_num|
|
51
|
+
|
52
|
+
meta = Meta.deserialize(meta)
|
112
53
|
|
113
54
|
# Get rule set.
|
114
55
|
rule_set = get_input_rule_set(klass, method, arg_num)
|
@@ -135,7 +76,7 @@ class Aggregator
|
|
135
76
|
end
|
136
77
|
|
137
78
|
# Train on metadata.
|
138
|
-
output_rule_set.train(
|
79
|
+
output_rule_set.train(Meta.deserialize(control["output"]))
|
139
80
|
|
140
81
|
end
|
141
82
|
|
@@ -144,22 +85,23 @@ class Aggregator
|
|
144
85
|
##
|
145
86
|
# Validate inputs.
|
146
87
|
#
|
88
|
+
# @stage Called when validating a reflection.
|
147
89
|
# @param inputs [Array] The method's arguments.
|
148
90
|
# @param input_rule_sets [Array] The RuleSets to validate each input with.
|
149
91
|
##
|
150
|
-
def
|
92
|
+
def test_inputs(inputs, input_rule_sets)
|
151
93
|
|
152
|
-
# Default to
|
94
|
+
# Default result to PASS.
|
153
95
|
result = true
|
154
96
|
|
155
|
-
# Validate each argument against each
|
97
|
+
# Validate each argument against each rule set for that argument.
|
156
98
|
inputs.each_with_index do |input, arg_num|
|
157
99
|
|
158
100
|
unless input_rule_sets[arg_num].nil?
|
159
101
|
|
160
102
|
rule_set = input_rule_sets[arg_num]
|
161
103
|
|
162
|
-
unless rule_set.
|
104
|
+
unless rule_set.test(input)
|
163
105
|
result = false
|
164
106
|
end
|
165
107
|
|
@@ -173,10 +115,11 @@ class Aggregator
|
|
173
115
|
##
|
174
116
|
# Validate output.
|
175
117
|
#
|
118
|
+
# @stage Called when validating a reflection.
|
176
119
|
# @param output [Dynamic] The method's return value.
|
177
120
|
# @param output_rule_set [RuleSet] The RuleSet to validate the output with.
|
178
121
|
##
|
179
|
-
def
|
122
|
+
def test_output(output, output_rule_set)
|
180
123
|
|
181
124
|
# Default to a PASS result.
|
182
125
|
result = true
|
@@ -184,7 +127,7 @@ class Aggregator
|
|
184
127
|
unless output_rule_set.nil?
|
185
128
|
|
186
129
|
# Validate output RuleSet for that argument.
|
187
|
-
unless output_rule_set.
|
130
|
+
unless output_rule_set.test(output)
|
188
131
|
result = false
|
189
132
|
end
|
190
133
|
|
@@ -194,4 +137,115 @@ class Aggregator
|
|
194
137
|
|
195
138
|
end
|
196
139
|
|
140
|
+
##
|
141
|
+
# Get aggregated RuleSets for all inputs.
|
142
|
+
#
|
143
|
+
# @stage Called when building a reflection.
|
144
|
+
# @param klass [Symbol]
|
145
|
+
# @param method [Symbol]
|
146
|
+
# @return [Array]
|
147
|
+
##
|
148
|
+
def get_input_rule_sets(klass, method)
|
149
|
+
@rule_sets.dig(klass, method, :inputs)
|
150
|
+
end
|
151
|
+
|
152
|
+
##
|
153
|
+
# Get an aggregated RuleSet for an output.
|
154
|
+
#
|
155
|
+
# @stage Called when building a reflection.
|
156
|
+
# @param klass [Symbol]
|
157
|
+
# @param method [Symbol]
|
158
|
+
# @return [RuleSet]
|
159
|
+
##
|
160
|
+
def get_output_rule_set(klass, method)
|
161
|
+
@rule_sets.dig(klass, method, :output)
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# Get the base rule type for a data type.
|
166
|
+
##
|
167
|
+
def self.value_to_rule_type(value)
|
168
|
+
|
169
|
+
data_type = value.class
|
170
|
+
|
171
|
+
rule_types = {
|
172
|
+
Array => ArrayRule,
|
173
|
+
TrueClass => BooleanRule,
|
174
|
+
FalseClass => BooleanRule,
|
175
|
+
Float => FloatRule,
|
176
|
+
Integer => IntegerRule,
|
177
|
+
NilClass => NullRule,
|
178
|
+
String => StringRule
|
179
|
+
}
|
180
|
+
|
181
|
+
return rule_types[data_type]
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.testable?(args, input_rule_sets)
|
186
|
+
|
187
|
+
args.each_with_index do |arg, arg_num|
|
188
|
+
|
189
|
+
rule_type = value_to_rule_type(arg)
|
190
|
+
if input_rule_sets[arg_num].rules[rule_type].nil?
|
191
|
+
return false
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
return true
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
##############################################################################
|
201
|
+
# HELPERS
|
202
|
+
##############################################################################
|
203
|
+
|
204
|
+
private
|
205
|
+
|
206
|
+
##
|
207
|
+
# Get an aggregated RuleSet for an input.
|
208
|
+
#
|
209
|
+
# @param klass [Symbol]
|
210
|
+
# @param method [Symbol]
|
211
|
+
# @return [RuleSet]
|
212
|
+
##
|
213
|
+
def get_input_rule_set(klass, method, arg_num)
|
214
|
+
@rule_sets.dig(klass, method, :inputs, arg_num)
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# Set an aggregated RuleSet for an input.
|
219
|
+
#
|
220
|
+
# @param klass [Symbol]
|
221
|
+
# @param method [Symbol]
|
222
|
+
##
|
223
|
+
def set_input_rule_set(klass, method, arg_num, rule_set)
|
224
|
+
|
225
|
+
# Set defaults.
|
226
|
+
@rule_sets[klass] = {} unless @rule_sets.key? klass
|
227
|
+
@rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
|
228
|
+
@rule_sets[klass][method][:inputs] = [] unless @rule_sets[klass][method].key? :inputs
|
229
|
+
# Set value.
|
230
|
+
@rule_sets[klass][method][:inputs][arg_num] = rule_set
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
##
|
235
|
+
# Set an aggregated RuleSet for an output.
|
236
|
+
#
|
237
|
+
# @param klass [Symbol]
|
238
|
+
# @param method [Symbol]
|
239
|
+
# @param rule_set [RuleSet]
|
240
|
+
##
|
241
|
+
def set_output_rule_set(klass, method, rule_set)
|
242
|
+
|
243
|
+
# Set defaults.
|
244
|
+
@rule_sets[klass] = {} unless @rule_sets.key? klass
|
245
|
+
@rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
|
246
|
+
# Set value.
|
247
|
+
@rule_sets[klass][method][:output] = rule_set
|
248
|
+
|
249
|
+
end
|
250
|
+
|
197
251
|
end
|
data/lib/Clone.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
################################################################################
|
2
|
+
# A clone of the instance that a reflection calls methods on,
|
3
|
+
# as well as any other instances that those methods may lead to.
|
4
|
+
#
|
5
|
+
# @note
|
6
|
+
# Not currently in use due to bug where "send" needs to be called directly
|
7
|
+
# on object, not indirectly through clone which results in "undefined method".
|
8
|
+
#
|
9
|
+
# @hierachy
|
10
|
+
# 1. Execution
|
11
|
+
# 2. Reflection
|
12
|
+
# 3. Clone <- YOU ARE HERE
|
13
|
+
################################################################################
|
14
|
+
|
15
|
+
class Clone
|
16
|
+
|
17
|
+
def initialize(execution)
|
18
|
+
|
19
|
+
# Clone the execution's calling object.
|
20
|
+
@caller_object_clone = execution.caller_object.clone
|
21
|
+
|
22
|
+
# TODO: Clone any other instances that this clone references.
|
23
|
+
# TODO: Replace clone's references to these new instances.
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def action(method, *new_args)
|
28
|
+
@caller_object_clone.send(method, *new_args)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/lib/Config.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class Config
|
2
2
|
|
3
|
+
attr_accessor :enabled
|
3
4
|
attr_accessor :reflect_amount
|
4
5
|
attr_accessor :reflect_limit
|
5
6
|
attr_accessor :meta_map
|
@@ -8,8 +9,12 @@ class Config
|
|
8
9
|
|
9
10
|
def initialize()
|
10
11
|
|
12
|
+
# Reflekt is enabled by default and should be disabled on production.
|
13
|
+
@enabled = true
|
14
|
+
|
11
15
|
# The amount of reflections to create per method call.
|
12
|
-
|
16
|
+
# A control reflection is created in addition to this.
|
17
|
+
@reflect_amount = 5
|
13
18
|
|
14
19
|
# The maximum amount of reflections that can be created per instance/method.
|
15
20
|
# A method called thousands of times doesn't need that many reflections.
|
@@ -20,6 +25,8 @@ class Config
|
|
20
25
|
:array => [ArrayRule],
|
21
26
|
:bool => [BooleanRule],
|
22
27
|
:int => [IntegerRule],
|
28
|
+
:float => [FloatRule],
|
29
|
+
:null => [NullRule],
|
23
30
|
:string => [StringRule]
|
24
31
|
}
|
25
32
|
|
data/lib/Control.rb
CHANGED
@@ -1,10 +1,21 @@
|
|
1
1
|
################################################################################
|
2
2
|
# A shapshot of real data.
|
3
3
|
#
|
4
|
+
# @note
|
5
|
+
# A control's @number property will always be zero.
|
6
|
+
#
|
7
|
+
# @nomenclature
|
8
|
+
# args, inputs/output and meta represent different stages of a value.
|
9
|
+
#
|
4
10
|
# @hierachy
|
5
11
|
# 1. Execution
|
6
|
-
# 2. Control
|
7
|
-
# 3.
|
12
|
+
# 2. Control <- YOU ARE HERE
|
13
|
+
# 3. Meta
|
14
|
+
#
|
15
|
+
# @status
|
16
|
+
# - :pass [Symbol] The reflection passes the rules.
|
17
|
+
# - :fail [Symbol] The reflection fails the rules or produces a system error.
|
18
|
+
# - :error [Symbol] The control reflection produces a system error.
|
8
19
|
################################################################################
|
9
20
|
|
10
21
|
require 'Reflection'
|
@@ -15,27 +26,54 @@ class Control < Reflection
|
|
15
26
|
##
|
16
27
|
# Reflect on a method.
|
17
28
|
#
|
18
|
-
# Creates a shadow execution
|
19
|
-
#
|
20
|
-
# @param method [Symbol] The name of the method.
|
21
|
-
# @param *args [Args] The method arguments.
|
22
|
-
# @return [Hash] A reflection hash.
|
29
|
+
# Creates a shadow execution.
|
30
|
+
# @param *args [Dynamic] The method's arguments.
|
23
31
|
##
|
24
32
|
def reflect(*args)
|
25
33
|
|
26
|
-
#
|
27
|
-
|
34
|
+
# Get aggregated rule sets.
|
35
|
+
input_rule_sets = @aggregator.get_input_rule_sets(@klass, @method)
|
36
|
+
output_rule_set = @aggregator.get_output_rule_set(@klass, @method)
|
37
|
+
|
38
|
+
# When arguments exist.
|
39
|
+
unless args.size == 0
|
40
|
+
|
41
|
+
# When aggregated rule sets exist.
|
42
|
+
unless input_rule_sets.nil?
|
43
|
+
|
44
|
+
# Validate arguments against aggregated rule sets.
|
45
|
+
unless @aggregator.test_inputs(args, input_rule_sets)
|
46
|
+
@status = :fail
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
28
50
|
|
29
|
-
|
51
|
+
# Create metadata for each argument.
|
52
|
+
# TODO: Create metadata for other inputs such as properties on the instance.
|
53
|
+
@inputs = MetaBuilder.create_many(args)
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# Action method with new/old arguments.
|
30
58
|
begin
|
59
|
+
|
60
|
+
# Run reflection.
|
31
61
|
output = @clone.send(@method, *args)
|
32
|
-
|
62
|
+
@output = MetaBuilder.create(output)
|
63
|
+
|
64
|
+
# Validate output with aggregated control rule sets.
|
65
|
+
unless output_rule_set.nil?
|
66
|
+
unless @aggregator.test_output(output, output_rule_set)
|
67
|
+
@status = :fail
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# When a system error occurs.
|
33
72
|
rescue StandardError => message
|
34
|
-
|
73
|
+
|
74
|
+
@status = :error
|
35
75
|
@message = message
|
36
|
-
|
37
|
-
else
|
38
|
-
@status = :pass
|
76
|
+
|
39
77
|
end
|
40
78
|
|
41
79
|
end
|