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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/lib/accessor.rb +45 -0
  3. data/lib/action.rb +127 -0
  4. data/lib/action_stack.rb +44 -0
  5. data/lib/{Clone.rb → clone.rb} +11 -11
  6. data/lib/config.rb +48 -0
  7. data/lib/control.rb +81 -0
  8. data/lib/experiment.rb +99 -0
  9. data/lib/meta.rb +75 -0
  10. data/lib/meta/array_meta.rb +32 -0
  11. data/lib/meta/boolean_meta.rb +26 -0
  12. data/lib/meta/float_meta.rb +26 -0
  13. data/lib/meta/integer_meta.rb +26 -0
  14. data/lib/meta/{NullMeta.rb → null_meta.rb} +21 -19
  15. data/lib/meta/object_meta.rb +35 -0
  16. data/lib/meta/string_meta.rb +26 -0
  17. data/lib/meta_builder.rb +100 -0
  18. data/lib/reflection.rb +123 -0
  19. data/lib/reflekt.rb +277 -0
  20. data/lib/renderer.rb +38 -0
  21. data/lib/rule.rb +54 -0
  22. data/lib/rule_set.rb +110 -0
  23. data/lib/rule_set_aggregator.rb +260 -0
  24. data/lib/rules/array_rule.rb +94 -0
  25. data/lib/rules/boolean_rule.rb +43 -0
  26. data/lib/rules/float_rule.rb +55 -0
  27. data/lib/rules/integer_rule.rb +55 -0
  28. data/lib/rules/null_rule.rb +35 -0
  29. data/lib/rules/object_rule.rb +42 -0
  30. data/lib/rules/string_rule.rb +75 -0
  31. data/lib/web/index.html +3 -4
  32. metadata +46 -29
  33. data/lib/Accessor.rb +0 -37
  34. data/lib/Action.rb +0 -88
  35. data/lib/ActionStack.rb +0 -44
  36. data/lib/Aggregator.rb +0 -260
  37. data/lib/Config.rb +0 -42
  38. data/lib/Control.rb +0 -83
  39. data/lib/Meta.rb +0 -71
  40. data/lib/MetaBuilder.rb +0 -84
  41. data/lib/Reflection.rb +0 -195
  42. data/lib/Reflekt.rb +0 -243
  43. data/lib/Renderer.rb +0 -39
  44. data/lib/Rule.rb +0 -52
  45. data/lib/RuleSet.rb +0 -109
  46. data/lib/meta/ArrayMeta.rb +0 -34
  47. data/lib/meta/BooleanMeta.rb +0 -26
  48. data/lib/meta/FloatMeta.rb +0 -26
  49. data/lib/meta/IntegerMeta.rb +0 -26
  50. data/lib/meta/StringMeta.rb +0 -26
  51. data/lib/rules/ArrayRule.rb +0 -88
  52. data/lib/rules/BooleanRule.rb +0 -47
  53. data/lib/rules/FloatRule.rb +0 -57
  54. data/lib/rules/IntegerRule.rb +0 -57
  55. data/lib/rules/NullRule.rb +0 -33
  56. data/lib/rules/StringRule.rb +0 -81
@@ -0,0 +1,260 @@
1
+ ################################################################################
2
+ # Aggregate control metadata into rule sets.
3
+ # Validate reflections against aggregated controls.
4
+ #
5
+ # @pattern Singleton
6
+ #
7
+ # @hierachy
8
+ # 1. RuleSetAggregator <- YOU ARE HERE
9
+ # 2. RuleSet
10
+ # 3. Rule
11
+ ################################################################################
12
+
13
+ require_relative 'rule_set'
14
+
15
+ module Reflekt
16
+ class RuleSetAggregator
17
+
18
+ ##
19
+ # @param meta_map [Hash] The rules that apply to each meta type.
20
+ ##
21
+ def initialize(meta_map)
22
+ @meta_map = meta_map
23
+ # Key rule sets by class and method.
24
+ @rule_sets = {}
25
+ end
26
+
27
+ ##
28
+ # Create aggregated rule sets from control metadata.
29
+ #
30
+ # @stage Called on setup.
31
+ # @param controls [Array] Controls with metadata.
32
+ # @TODO Revert string keys to symbols once "Fix Rowdb.get(path)" bug fixed.
33
+ ##
34
+ def train(controls)
35
+
36
+ # On first use there are no previous controls.
37
+ return if controls.nil?
38
+
39
+ controls.each do |control|
40
+
41
+ klass = control["class"].to_sym
42
+ method = control["method"].to_sym
43
+
44
+ ##
45
+ # INPUT
46
+ ##
47
+
48
+ # Singular null input.
49
+ if control["inputs"].nil?
50
+ train_input(klass, method, nil, 0)
51
+ # Multiple inputs.
52
+ else
53
+ control["inputs"].each_with_index do |meta, arg_num|
54
+ train_input(klass, method, meta, arg_num)
55
+ end
56
+ end
57
+
58
+ ##
59
+ # OUTPUT
60
+ ##
61
+
62
+ # Get rule set.
63
+ output_rule_set = get_output_rule_set(klass, method)
64
+ if output_rule_set.nil?
65
+ output_rule_set = RuleSet.new(@meta_map)
66
+ set_output_rule_set(klass, method, output_rule_set)
67
+ end
68
+
69
+ # Train on metadata.
70
+ output_rule_set.train(Meta.deserialize(control["output"]))
71
+
72
+ end
73
+
74
+ end
75
+
76
+ def train_input(klass, method, meta, arg_num)
77
+
78
+ # Get deserialized meta.
79
+ meta = Meta.deserialize(meta)
80
+
81
+ # Get rule set.
82
+ rule_set = get_input_rule_set(klass, method, arg_num)
83
+ if rule_set.nil?
84
+ rule_set = RuleSet.new(@meta_map)
85
+ set_input_rule_set(klass, method, arg_num, rule_set)
86
+ end
87
+
88
+ # Train on metadata.
89
+ rule_set.train(meta)
90
+
91
+ end
92
+
93
+ ##
94
+ # Validate inputs.
95
+ #
96
+ # @stage Called when validating a control reflection.
97
+ # @param inputs [Array] The method's arguments.
98
+ # @param input_rule_sets [Array] The RuleSets to validate each input with.
99
+ ##
100
+ def test_inputs(inputs, input_rule_sets)
101
+
102
+ # Default result to PASS.
103
+ result = true
104
+
105
+ # Validate each argument against each rule set for that argument.
106
+ inputs.each_with_index do |input, arg_num|
107
+
108
+ unless input_rule_sets[arg_num].nil?
109
+
110
+ rule_set = input_rule_sets[arg_num]
111
+
112
+ unless rule_set.test(input)
113
+ result = false
114
+ end
115
+
116
+ end
117
+ end
118
+
119
+ return result
120
+
121
+ end
122
+
123
+ ##
124
+ # Validate output.
125
+ #
126
+ # @stage Called when validating a reflection.
127
+ # @param output [Dynamic] The method's return value.
128
+ # @param output_rule_set [RuleSet] The rule set to validate the output with.
129
+ ##
130
+ def test_output(output, output_rule_set)
131
+
132
+ # Default to a PASS result.
133
+ result = true
134
+
135
+ unless output_rule_set.nil?
136
+
137
+ # Validate output rule set for that argument.
138
+ unless output_rule_set.test(output)
139
+ result = false
140
+ end
141
+
142
+ end
143
+
144
+ return result
145
+
146
+ end
147
+
148
+ ##
149
+ # Get aggregated RuleSets for all inputs.
150
+ #
151
+ # @stage Called when building a reflection.
152
+ # @param klass [Symbol]
153
+ # @param method [Symbol]
154
+ # @return [Array]
155
+ ##
156
+ def get_input_rule_sets(klass, method)
157
+ @rule_sets.dig(klass, method, :inputs)
158
+ end
159
+
160
+ ##
161
+ # Get an aggregated RuleSet for an output.
162
+ #
163
+ # @stage Called when building a reflection.
164
+ # @param klass [Symbol]
165
+ # @param method [Symbol]
166
+ # @return [RuleSet]
167
+ ##
168
+ def get_output_rule_set(klass, method)
169
+ @rule_sets.dig(klass, method, :output)
170
+ end
171
+
172
+ ##
173
+ # Get the base rule type for a data type.
174
+ ##
175
+ def self.value_to_rule_type(value)
176
+
177
+ data_type = value.class
178
+
179
+ rule_types = {
180
+ Array => ArrayRule,
181
+ TrueClass => BooleanRule,
182
+ FalseClass => BooleanRule,
183
+ Float => FloatRule,
184
+ Integer => IntegerRule,
185
+ NilClass => NullRule,
186
+ String => StringRule
187
+ }
188
+
189
+ return rule_types[data_type]
190
+
191
+ end
192
+
193
+ def self.testable?(args, input_rule_sets)
194
+
195
+ args.each_with_index do |arg, arg_num|
196
+
197
+ rule_type = value_to_rule_type(arg)
198
+ if input_rule_sets[arg_num].rules[rule_type].nil?
199
+ return false
200
+ end
201
+
202
+ end
203
+
204
+ return true
205
+
206
+ end
207
+
208
+ ##############################################################################
209
+ # HELPERS
210
+ ##############################################################################
211
+
212
+ private
213
+
214
+ ##
215
+ # Get an aggregated RuleSet for an input.
216
+ #
217
+ # @param klass [Symbol]
218
+ # @param method [Symbol]
219
+ # @return [RuleSet]
220
+ ##
221
+ def get_input_rule_set(klass, method, arg_num)
222
+ @rule_sets.dig(klass, method, :inputs, arg_num)
223
+ end
224
+
225
+ ##
226
+ # Set an aggregated RuleSet for an input.
227
+ #
228
+ # @param klass [Symbol]
229
+ # @param method [Symbol]
230
+ ##
231
+ def set_input_rule_set(klass, method, arg_num, rule_set)
232
+
233
+ # Set defaults.
234
+ @rule_sets[klass] = {} unless @rule_sets.key? klass
235
+ @rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
236
+ @rule_sets[klass][method][:inputs] = [] unless @rule_sets[klass][method].key? :inputs
237
+ # Set value.
238
+ @rule_sets[klass][method][:inputs][arg_num] = rule_set
239
+
240
+ end
241
+
242
+ ##
243
+ # Set an aggregated RuleSet for an output.
244
+ #
245
+ # @param klass [Symbol]
246
+ # @param method [Symbol]
247
+ # @param rule_set [RuleSet]
248
+ ##
249
+ def set_output_rule_set(klass, method, rule_set)
250
+
251
+ # Set defaults.
252
+ @rule_sets[klass] = {} unless @rule_sets.key? klass
253
+ @rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
254
+ # Set value.
255
+ @rule_sets[klass][method][:output] = rule_set
256
+
257
+ end
258
+
259
+ end
260
+ end
@@ -0,0 +1,94 @@
1
+ require_relative '../rule'
2
+
3
+ module Reflekt
4
+ class ArrayRule < Rule
5
+
6
+ def initialize()
7
+ @type = :array
8
+ @min = nil
9
+ @max = nil
10
+ @min_length = nil
11
+ @max_length = nil
12
+ end
13
+
14
+ ##
15
+ # @param meta [ArrayMeta]
16
+ ##
17
+ def train(meta)
18
+ if Meta.numeric? meta[:min]
19
+ # Min value.
20
+ meta_min = meta[:min].to_i
21
+ if @min.nil?
22
+ @min = meta_min
23
+ else
24
+ @min = meta_min if meta_min < @min
25
+ end
26
+
27
+ # Max value.
28
+ meta_max = meta[:max].to_i
29
+ if @max.nil?
30
+ @max = meta_max
31
+ else
32
+ @max = meta_max if meta_max > @max
33
+ end
34
+ end
35
+
36
+ # Min length.
37
+ if @min_length.nil?
38
+ @min_length = meta[:length]
39
+ else
40
+ @min_length = meta[:length] if meta[:length] < @min_length
41
+ end
42
+
43
+ # Max length.
44
+ if @max_length.nil?
45
+ @max_length = meta[:length]
46
+ else
47
+ @max_length = meta[:length] if meta[:length] > @max_length
48
+ end
49
+ end
50
+
51
+ ##
52
+ # @param value [Array]
53
+ ##
54
+ def test(value)
55
+ # Handle empty value.
56
+ return true if value.empty? && @min_length == 0 && @max_length == 0
57
+
58
+ unless value.empty?
59
+ # Numbers only; if the value is a string then there will be no min/max.
60
+ unless @min.nil? || @max.nil?
61
+ return false if value.min() < @min
62
+ return false if value.max() > @max
63
+ end
64
+
65
+ # Min/max length.
66
+ return false if value.length < @min_length
67
+ return false if value.length > @max_length
68
+ end
69
+
70
+ true
71
+ end
72
+
73
+ def result()
74
+ {
75
+ :type => @type,
76
+ :min => @min,
77
+ :max => @max,
78
+ :min_length => @min_length,
79
+ :max_length => @max_length
80
+ }
81
+ end
82
+
83
+ def random()
84
+ array = Array.new(rand(@min_length..@max_length))
85
+
86
+ array.each_with_index do |item, index|
87
+ array[index] = rand(@min..@max)
88
+ end
89
+
90
+ return array
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,43 @@
1
+ require 'set'
2
+ require_relative '../rule'
3
+
4
+ module Reflekt
5
+ class BooleanRule < Rule
6
+
7
+ def initialize()
8
+ @type = :bool
9
+ @booleans = Set.new()
10
+ end
11
+
12
+ ##
13
+ # @param meta [BooleanMeta]
14
+ ##
15
+ def train(meta)
16
+ value = meta[:value]
17
+
18
+ unless value.nil?
19
+ @booleans << value
20
+ end
21
+ end
22
+
23
+ ##
24
+ # @param value [Boolean]
25
+ ##
26
+ def test(value)
27
+ # Booleans are stored as strings.
28
+ @booleans.include? value.to_s
29
+ end
30
+
31
+ def result()
32
+ {
33
+ :type => @type,
34
+ :booleans => @booleans
35
+ }
36
+ end
37
+
38
+ def random()
39
+ @booleans.to_a.sample
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ require_relative '../rule'
2
+
3
+ module Reflekt
4
+ class FloatRule < Rule
5
+
6
+ def initialize()
7
+ @type = :float
8
+ @min = nil
9
+ @max = nil
10
+ end
11
+
12
+ ##
13
+ # @param meta [FloatMeta]
14
+ ##
15
+ def train(meta)
16
+ value = meta[:value]
17
+
18
+ if @min.nil?
19
+ @min = value
20
+ else
21
+ @min = value if value < @min
22
+ end
23
+
24
+ if @max.nil?
25
+ @max = value
26
+ else
27
+ @max = value if value > @max
28
+ end
29
+ end
30
+
31
+ ##
32
+ # @param value [Float]
33
+ ##
34
+ def test(value)
35
+ # Numbers only; if the value is a string then there will be no min/max.
36
+ unless @min.nil? || @max.nil?
37
+ return false if value < @min
38
+ return false if value > @max
39
+ end
40
+ end
41
+
42
+ def result()
43
+ {
44
+ :type => @type,
45
+ :min => @min,
46
+ :max => @max
47
+ }
48
+ end
49
+
50
+ def random()
51
+ rand(@min..@max)
52
+ end
53
+
54
+ end
55
+ end