reflekt 1.0.5 → 1.0.10
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 +45 -0
- data/lib/action.rb +127 -0
- data/lib/action_stack.rb +44 -0
- data/lib/{Clone.rb → clone.rb} +11 -11
- data/lib/config.rb +48 -0
- data/lib/control.rb +81 -0
- data/lib/experiment.rb +99 -0
- data/lib/meta.rb +75 -0
- data/lib/meta/array_meta.rb +32 -0
- data/lib/meta/boolean_meta.rb +26 -0
- data/lib/meta/float_meta.rb +26 -0
- data/lib/meta/integer_meta.rb +26 -0
- data/lib/meta/{NullMeta.rb → null_meta.rb} +21 -19
- data/lib/meta/object_meta.rb +35 -0
- data/lib/meta/string_meta.rb +26 -0
- data/lib/meta_builder.rb +100 -0
- data/lib/reflection.rb +123 -0
- data/lib/reflekt.rb +277 -0
- data/lib/renderer.rb +38 -0
- data/lib/rule.rb +54 -0
- data/lib/rule_set.rb +110 -0
- data/lib/rule_set_aggregator.rb +260 -0
- data/lib/rules/array_rule.rb +94 -0
- data/lib/rules/boolean_rule.rb +43 -0
- data/lib/rules/float_rule.rb +55 -0
- data/lib/rules/integer_rule.rb +55 -0
- data/lib/rules/null_rule.rb +35 -0
- data/lib/rules/object_rule.rb +42 -0
- data/lib/rules/string_rule.rb +75 -0
- data/lib/web/index.html +3 -4
- metadata +46 -29
- data/lib/Accessor.rb +0 -37
- data/lib/Action.rb +0 -88
- data/lib/ActionStack.rb +0 -44
- data/lib/Aggregator.rb +0 -260
- data/lib/Config.rb +0 -42
- data/lib/Control.rb +0 -83
- data/lib/Meta.rb +0 -71
- data/lib/MetaBuilder.rb +0 -84
- data/lib/Reflection.rb +0 -195
- data/lib/Reflekt.rb +0 -243
- data/lib/Renderer.rb +0 -39
- data/lib/Rule.rb +0 -52
- data/lib/RuleSet.rb +0 -109
- data/lib/meta/ArrayMeta.rb +0 -34
- data/lib/meta/BooleanMeta.rb +0 -26
- data/lib/meta/FloatMeta.rb +0 -26
- data/lib/meta/IntegerMeta.rb +0 -26
- data/lib/meta/StringMeta.rb +0 -26
- data/lib/rules/ArrayRule.rb +0 -88
- data/lib/rules/BooleanRule.rb +0 -47
- data/lib/rules/FloatRule.rb +0 -57
- data/lib/rules/IntegerRule.rb +0 -57
- data/lib/rules/NullRule.rb +0 -33
- data/lib/rules/StringRule.rb +0 -81
data/lib/ActionStack.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
################################################################################
|
2
|
-
# Track the actions in a shadow call stack.
|
3
|
-
#
|
4
|
-
# @pattern Stack
|
5
|
-
################################################################################
|
6
|
-
|
7
|
-
class ActionStack
|
8
|
-
|
9
|
-
def initialize()
|
10
|
-
@bottom = nil
|
11
|
-
@top = nil
|
12
|
-
end
|
13
|
-
|
14
|
-
def peek()
|
15
|
-
@top
|
16
|
-
end
|
17
|
-
|
18
|
-
def base()
|
19
|
-
@bottom
|
20
|
-
end
|
21
|
-
|
22
|
-
##
|
23
|
-
# Place Action at the top of stack.
|
24
|
-
#
|
25
|
-
# @param action [Action] The action to place.
|
26
|
-
# @return [Action] The placed action.
|
27
|
-
##
|
28
|
-
def push(action)
|
29
|
-
|
30
|
-
# Place first action at bottom of stack.
|
31
|
-
if @bottom.nil?
|
32
|
-
@bottom = action
|
33
|
-
# Connect subsequent actions to each other.
|
34
|
-
else
|
35
|
-
@top.parent = action
|
36
|
-
action.child = @top
|
37
|
-
end
|
38
|
-
|
39
|
-
# Place action at top of stack.
|
40
|
-
@top = action
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
data/lib/Aggregator.rb
DELETED
@@ -1,260 +0,0 @@
|
|
1
|
-
################################################################################
|
2
|
-
# Aggregate control metadata into rule sets.
|
3
|
-
# Validate reflections against aggregated controls.
|
4
|
-
#
|
5
|
-
# @pattern Singleton
|
6
|
-
#
|
7
|
-
# @hierachy
|
8
|
-
# 1. Aggregator <- YOU ARE HERE
|
9
|
-
# 2. RuleSet
|
10
|
-
# 3. Rule
|
11
|
-
################################################################################
|
12
|
-
|
13
|
-
require 'RuleSet'
|
14
|
-
|
15
|
-
class Aggregator
|
16
|
-
|
17
|
-
##
|
18
|
-
# @param meta_map [Hash] The rules that apply to each meta type.
|
19
|
-
##
|
20
|
-
def initialize(meta_map)
|
21
|
-
|
22
|
-
@meta_map = meta_map
|
23
|
-
# Key rule sets by class and method.
|
24
|
-
@rule_sets = {}
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
##
|
29
|
-
# Create aggregated rule sets from control metadata.
|
30
|
-
#
|
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
|
-
##
|
35
|
-
def train(controls)
|
36
|
-
|
37
|
-
# On first use there are no previous controls.
|
38
|
-
return if controls.nil?
|
39
|
-
|
40
|
-
controls.each do |control|
|
41
|
-
|
42
|
-
klass = control["class"].to_sym
|
43
|
-
method = control["method"].to_sym
|
44
|
-
|
45
|
-
##
|
46
|
-
# INPUT
|
47
|
-
##
|
48
|
-
|
49
|
-
# Singular null input.
|
50
|
-
if control["inputs"].nil?
|
51
|
-
train_input(klass, method, nil, 0)
|
52
|
-
# Multiple inputs.
|
53
|
-
else
|
54
|
-
control["inputs"].each_with_index do |meta, arg_num|
|
55
|
-
train_input(klass, method, meta, arg_num)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
##
|
60
|
-
# OUTPUT
|
61
|
-
##
|
62
|
-
|
63
|
-
# Get rule set.
|
64
|
-
output_rule_set = get_output_rule_set(klass, method)
|
65
|
-
if output_rule_set.nil?
|
66
|
-
output_rule_set = RuleSet.new(@meta_map)
|
67
|
-
set_output_rule_set(klass, method, output_rule_set)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Train on metadata.
|
71
|
-
output_rule_set.train(Meta.deserialize(control["output"]))
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
def train_input(klass, method, meta, arg_num)
|
78
|
-
|
79
|
-
# Get deserialized meta.
|
80
|
-
meta = Meta.deserialize(meta)
|
81
|
-
|
82
|
-
# Get rule set.
|
83
|
-
rule_set = get_input_rule_set(klass, method, arg_num)
|
84
|
-
if rule_set.nil?
|
85
|
-
rule_set = RuleSet.new(@meta_map)
|
86
|
-
set_input_rule_set(klass, method, arg_num, rule_set)
|
87
|
-
end
|
88
|
-
|
89
|
-
# Train on metadata.
|
90
|
-
rule_set.train(meta)
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
##
|
95
|
-
# Validate inputs.
|
96
|
-
#
|
97
|
-
# @stage Called when validating a control reflection.
|
98
|
-
# @param inputs [Array] The method's arguments.
|
99
|
-
# @param input_rule_sets [Array] The RuleSets to validate each input with.
|
100
|
-
##
|
101
|
-
def test_inputs(inputs, input_rule_sets)
|
102
|
-
|
103
|
-
# Default result to PASS.
|
104
|
-
result = true
|
105
|
-
|
106
|
-
# Validate each argument against each rule set for that argument.
|
107
|
-
inputs.each_with_index do |input, arg_num|
|
108
|
-
|
109
|
-
unless input_rule_sets[arg_num].nil?
|
110
|
-
|
111
|
-
rule_set = input_rule_sets[arg_num]
|
112
|
-
|
113
|
-
unless rule_set.test(input)
|
114
|
-
result = false
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
return result
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
##
|
125
|
-
# Validate output.
|
126
|
-
#
|
127
|
-
# @stage Called when validating a reflection.
|
128
|
-
# @param output [Dynamic] The method's return value.
|
129
|
-
# @param output_rule_set [RuleSet] The RuleSet to validate the output with.
|
130
|
-
##
|
131
|
-
def test_output(output, output_rule_set)
|
132
|
-
|
133
|
-
# Default to a PASS result.
|
134
|
-
result = true
|
135
|
-
|
136
|
-
unless output_rule_set.nil?
|
137
|
-
|
138
|
-
# Validate output RuleSet for that argument.
|
139
|
-
unless output_rule_set.test(output)
|
140
|
-
result = false
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
return result
|
146
|
-
|
147
|
-
end
|
148
|
-
|
149
|
-
##
|
150
|
-
# Get aggregated RuleSets for all inputs.
|
151
|
-
#
|
152
|
-
# @stage Called when building a reflection.
|
153
|
-
# @param klass [Symbol]
|
154
|
-
# @param method [Symbol]
|
155
|
-
# @return [Array]
|
156
|
-
##
|
157
|
-
def get_input_rule_sets(klass, method)
|
158
|
-
@rule_sets.dig(klass, method, :inputs)
|
159
|
-
end
|
160
|
-
|
161
|
-
##
|
162
|
-
# Get an aggregated RuleSet for an output.
|
163
|
-
#
|
164
|
-
# @stage Called when building a reflection.
|
165
|
-
# @param klass [Symbol]
|
166
|
-
# @param method [Symbol]
|
167
|
-
# @return [RuleSet]
|
168
|
-
##
|
169
|
-
def get_output_rule_set(klass, method)
|
170
|
-
@rule_sets.dig(klass, method, :output)
|
171
|
-
end
|
172
|
-
|
173
|
-
##
|
174
|
-
# Get the base rule type for a data type.
|
175
|
-
##
|
176
|
-
def self.value_to_rule_type(value)
|
177
|
-
|
178
|
-
data_type = value.class
|
179
|
-
|
180
|
-
rule_types = {
|
181
|
-
Array => ArrayRule,
|
182
|
-
TrueClass => BooleanRule,
|
183
|
-
FalseClass => BooleanRule,
|
184
|
-
Float => FloatRule,
|
185
|
-
Integer => IntegerRule,
|
186
|
-
NilClass => NullRule,
|
187
|
-
String => StringRule
|
188
|
-
}
|
189
|
-
|
190
|
-
return rule_types[data_type]
|
191
|
-
|
192
|
-
end
|
193
|
-
|
194
|
-
def self.testable?(args, input_rule_sets)
|
195
|
-
|
196
|
-
args.each_with_index do |arg, arg_num|
|
197
|
-
|
198
|
-
rule_type = value_to_rule_type(arg)
|
199
|
-
if input_rule_sets[arg_num].rules[rule_type].nil?
|
200
|
-
return false
|
201
|
-
end
|
202
|
-
|
203
|
-
end
|
204
|
-
|
205
|
-
return true
|
206
|
-
|
207
|
-
end
|
208
|
-
|
209
|
-
##############################################################################
|
210
|
-
# HELPERS
|
211
|
-
##############################################################################
|
212
|
-
|
213
|
-
private
|
214
|
-
|
215
|
-
##
|
216
|
-
# Get an aggregated RuleSet for an input.
|
217
|
-
#
|
218
|
-
# @param klass [Symbol]
|
219
|
-
# @param method [Symbol]
|
220
|
-
# @return [RuleSet]
|
221
|
-
##
|
222
|
-
def get_input_rule_set(klass, method, arg_num)
|
223
|
-
@rule_sets.dig(klass, method, :inputs, arg_num)
|
224
|
-
end
|
225
|
-
|
226
|
-
##
|
227
|
-
# Set an aggregated RuleSet for an input.
|
228
|
-
#
|
229
|
-
# @param klass [Symbol]
|
230
|
-
# @param method [Symbol]
|
231
|
-
##
|
232
|
-
def set_input_rule_set(klass, method, arg_num, rule_set)
|
233
|
-
|
234
|
-
# Set defaults.
|
235
|
-
@rule_sets[klass] = {} unless @rule_sets.key? klass
|
236
|
-
@rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
|
237
|
-
@rule_sets[klass][method][:inputs] = [] unless @rule_sets[klass][method].key? :inputs
|
238
|
-
# Set value.
|
239
|
-
@rule_sets[klass][method][:inputs][arg_num] = rule_set
|
240
|
-
|
241
|
-
end
|
242
|
-
|
243
|
-
##
|
244
|
-
# Set an aggregated RuleSet for an output.
|
245
|
-
#
|
246
|
-
# @param klass [Symbol]
|
247
|
-
# @param method [Symbol]
|
248
|
-
# @param rule_set [RuleSet]
|
249
|
-
##
|
250
|
-
def set_output_rule_set(klass, method, rule_set)
|
251
|
-
|
252
|
-
# Set defaults.
|
253
|
-
@rule_sets[klass] = {} unless @rule_sets.key? klass
|
254
|
-
@rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
|
255
|
-
# Set value.
|
256
|
-
@rule_sets[klass][method][:output] = rule_set
|
257
|
-
|
258
|
-
end
|
259
|
-
|
260
|
-
end
|
data/lib/Config.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
class Config
|
2
|
-
|
3
|
-
attr_accessor :enabled
|
4
|
-
attr_accessor :reflect_amount
|
5
|
-
attr_accessor :reflect_limit
|
6
|
-
attr_accessor :meta_map
|
7
|
-
attr_accessor :output_path
|
8
|
-
attr_accessor :output_directory
|
9
|
-
|
10
|
-
def initialize()
|
11
|
-
|
12
|
-
# Reflekt is enabled by default and should be disabled on production.
|
13
|
-
@enabled = true
|
14
|
-
|
15
|
-
# The amount of reflections to create per method call.
|
16
|
-
# A control reflection is created in addition to this.
|
17
|
-
@reflect_amount = 5
|
18
|
-
|
19
|
-
# The maximum amount of reflections that can be created per instance/method.
|
20
|
-
# A method called thousands of times doesn't need that many reflections.
|
21
|
-
@reflect_limit = 10
|
22
|
-
|
23
|
-
# The rules that apply to meta types.
|
24
|
-
@meta_map = {
|
25
|
-
:array => [ArrayRule],
|
26
|
-
:bool => [BooleanRule],
|
27
|
-
:int => [IntegerRule],
|
28
|
-
:float => [FloatRule],
|
29
|
-
:null => [NullRule],
|
30
|
-
:string => [StringRule]
|
31
|
-
}
|
32
|
-
|
33
|
-
# An absolute path to the directory that contains the output directory.
|
34
|
-
# Defaults to current action path.
|
35
|
-
@output_path = nil
|
36
|
-
|
37
|
-
# Name of output directory.
|
38
|
-
@output_directory = "reflections"
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
data/lib/Control.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
################################################################################
|
2
|
-
# A shapshot of real data.
|
3
|
-
#
|
4
|
-
# @note
|
5
|
-
# A control's @number will always be 0.
|
6
|
-
#
|
7
|
-
# @nomenclature
|
8
|
-
# args, inputs/output and meta represent different stages of a value.
|
9
|
-
#
|
10
|
-
# @hierachy
|
11
|
-
# 1. Action
|
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.
|
19
|
-
################################################################################
|
20
|
-
|
21
|
-
require 'Reflection'
|
22
|
-
require 'MetaBuilder'
|
23
|
-
|
24
|
-
class Control < Reflection
|
25
|
-
|
26
|
-
##
|
27
|
-
# Reflect on a method.
|
28
|
-
#
|
29
|
-
# Creates a shadow action.
|
30
|
-
# @param *args [Dynamic] The method's arguments.
|
31
|
-
##
|
32
|
-
def reflect(*args)
|
33
|
-
|
34
|
-
# Get trained 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
|
-
# Fail when no trained rule sets.
|
39
|
-
if input_rule_sets.nil?
|
40
|
-
@status = :fail
|
41
|
-
end
|
42
|
-
|
43
|
-
# When arguments exist.
|
44
|
-
unless args.size == 0
|
45
|
-
|
46
|
-
# Validate arguments against trained rule sets.
|
47
|
-
unless input_rule_sets.nil?
|
48
|
-
unless @aggregator.test_inputs(args, input_rule_sets)
|
49
|
-
@status = :fail
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Create metadata for each argument.
|
54
|
-
# TODO: Create metadata for other inputs such as instance variables.
|
55
|
-
@inputs = MetaBuilder.create_many(args)
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
# Action method with real arguments.
|
60
|
-
begin
|
61
|
-
|
62
|
-
# Run reflection.
|
63
|
-
output = @clone.send(@method, *args)
|
64
|
-
@output = MetaBuilder.create(output)
|
65
|
-
|
66
|
-
# Validate output with aggregated control rule sets.
|
67
|
-
unless output_rule_set.nil?
|
68
|
-
unless @aggregator.test_output(output, output_rule_set)
|
69
|
-
@status = :fail
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# When a system error occurs.
|
74
|
-
rescue StandardError => message
|
75
|
-
|
76
|
-
@status = :error
|
77
|
-
@message = message
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
data/lib/Meta.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
################################################################################
|
2
|
-
# Metadata for input and output.
|
3
|
-
#
|
4
|
-
# @pattern Abstract class
|
5
|
-
# @see lib/meta for each meta.
|
6
|
-
#
|
7
|
-
# @hierachy
|
8
|
-
# 1. Action
|
9
|
-
# 2. Reflection
|
10
|
-
# 3. Meta <- YOU ARE HERE
|
11
|
-
################################################################################
|
12
|
-
|
13
|
-
class Meta
|
14
|
-
|
15
|
-
##
|
16
|
-
# Each meta defines its type.
|
17
|
-
##
|
18
|
-
def initialize()
|
19
|
-
@type = :null
|
20
|
-
end
|
21
|
-
|
22
|
-
##
|
23
|
-
# Each meta loads values.
|
24
|
-
#
|
25
|
-
# @param value [Dynamic]
|
26
|
-
##
|
27
|
-
def load(value)
|
28
|
-
end
|
29
|
-
|
30
|
-
##
|
31
|
-
# @return [Hash]
|
32
|
-
##
|
33
|
-
def serialize()
|
34
|
-
{
|
35
|
-
:type => @type
|
36
|
-
}
|
37
|
-
end
|
38
|
-
|
39
|
-
##############################################################################
|
40
|
-
# CLASS
|
41
|
-
##############################################################################
|
42
|
-
|
43
|
-
##
|
44
|
-
# Deserialize metadata.
|
45
|
-
#
|
46
|
-
# @todo Deserialize should create a Meta object.
|
47
|
-
# @todo Require each Meta type to handle its own deserialization.
|
48
|
-
#
|
49
|
-
# @param meta [Hash] The metadata to deserialize.
|
50
|
-
# @param meta [Hash]
|
51
|
-
##
|
52
|
-
def self.deserialize(meta)
|
53
|
-
|
54
|
-
# Convert nil meta into NullMeta.
|
55
|
-
# Meta is nil when there are no @inputs or @output on the method.
|
56
|
-
if meta.nil?
|
57
|
-
return NullMeta.new().serialize()
|
58
|
-
end
|
59
|
-
|
60
|
-
# Symbolize keys.
|
61
|
-
# TODO: Remove once "Fix Rowdb.get(path)" bug fixed.
|
62
|
-
meta = meta.transform_keys(&:to_sym)
|
63
|
-
|
64
|
-
# Symbolize type value.
|
65
|
-
meta[:type] = meta[:type].to_sym
|
66
|
-
|
67
|
-
return meta
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|