reflekt 0.9.7 → 1.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6df15da98e45aecc17c3594c000b6234f77afde5ce89541104bc3afe7eb5a221
4
- data.tar.gz: 3f1446eb16bdcd214d3df924d0b2df0017bc26b073c5c94e36d1094849a9b1ef
3
+ metadata.gz: 7f9ff9a7d13d77e0e468cf961d6ef1dd6dd2c381b6d3d4fb1a1799b59aa1fdc6
4
+ data.tar.gz: 8bb82ca18b00bd0a1e329bd94557a164eff90fb607fbbcbfa6ef8b026f4619c9
5
5
  SHA512:
6
- metadata.gz: e84519473c26febf3522119e66b25708abc1f05271c01b498debcb00c69eaf4b8bc244e43374737fef49e946304529c0efc2e6fceade3629c4ccef5503f1d3fa
7
- data.tar.gz: 8faa3f80665504b4e5ffb182b7e9977234bd13e2f17aa5fac41636068b30ea07bfbf5aa580bee6deae2bb8e5fa6ea0ea7dc09505ce0a28bbf8797bb785aea0bb
6
+ metadata.gz: 9d22878d22a93be41323d89b6a718808f78fa61c8cc186ddde480a5298ea1a1ae1fc49576141186d3dee7c02a29295c67a59e41aa732ec1e9dc3b4fd878e7add
7
+ data.tar.gz: 2d759df0674e8dc496ae92b585588b2a927c8aa7bda0368be8265705e1340af60ebe393c84b059dd2516d23cb8f7577b7baa4fe016f1a17ed3934a9fbcc084a2
@@ -1,37 +1,36 @@
1
1
  ################################################################################
2
- # ACCESSOR
3
- #
4
2
  # Access variables via one object to avoid polluting the caller class scope.
5
3
  #
6
- # Some variables are not accessed via Accessor:
4
+ # @pattern Singleton
5
+ #
6
+ # @note Some variables are not accessed via Accessor:
7
7
  # - @reflekt_counts on the instance
8
- # - @reflekt_enabled on the instance
9
8
  # - @@reflekt_skipped_methods on the instance's singleton class
10
9
  ################################################################################
11
10
 
12
11
  class Accessor
13
12
 
13
+ attr_accessor :config
14
14
  attr_accessor :setup
15
15
  attr_accessor :db
16
16
  attr_accessor :stack
17
- attr_accessor :ruler
17
+ attr_accessor :aggregator
18
18
  attr_accessor :renderer
19
19
  attr_accessor :path
20
20
  attr_accessor :output_path
21
- attr_accessor :reflect_amount
22
- attr_accessor :reflect_limit
21
+ attr_accessor :error
23
22
 
24
23
  def initialize()
25
24
 
25
+ @config = nil
26
26
  @setup = nil
27
27
  @db = nil
28
28
  @stack = nil
29
- @ruler = nil
29
+ @aggregator = nil
30
30
  @renderer = nil
31
31
  @path = nil
32
32
  @output_path = nil
33
- @reflect_amount = nil
34
- @reflect_limit = nil
33
+ @error = false
35
34
 
36
35
  end
37
36
 
@@ -0,0 +1,251 @@
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
+ unless control["inputs"].nil?
50
+ control["inputs"].each_with_index do |meta, arg_num|
51
+
52
+ meta = Meta.deserialize(meta)
53
+
54
+ # Get rule set.
55
+ rule_set = get_input_rule_set(klass, method, arg_num)
56
+ if rule_set.nil?
57
+ rule_set = RuleSet.new(@meta_map)
58
+ set_input_rule_set(klass, method, arg_num, rule_set)
59
+ end
60
+
61
+ # Train on metadata.
62
+ rule_set.train(meta)
63
+
64
+ end
65
+ end
66
+
67
+ ##
68
+ # OUTPUT
69
+ ##
70
+
71
+ # Get rule set.
72
+ output_rule_set = get_output_rule_set(klass, method)
73
+ if output_rule_set.nil?
74
+ output_rule_set = RuleSet.new(@meta_map)
75
+ set_output_rule_set(klass, method, output_rule_set)
76
+ end
77
+
78
+ # Train on metadata.
79
+ output_rule_set.train(Meta.deserialize(control["output"]))
80
+
81
+ end
82
+
83
+ end
84
+
85
+ ##
86
+ # Validate inputs.
87
+ #
88
+ # @stage Called when validating a reflection.
89
+ # @param inputs [Array] The method's arguments.
90
+ # @param input_rule_sets [Array] The RuleSets to validate each input with.
91
+ ##
92
+ def test_inputs(inputs, input_rule_sets)
93
+
94
+ # Default result to PASS.
95
+ result = true
96
+
97
+ # Validate each argument against each rule set for that argument.
98
+ inputs.each_with_index do |input, arg_num|
99
+
100
+ unless input_rule_sets[arg_num].nil?
101
+
102
+ rule_set = input_rule_sets[arg_num]
103
+
104
+ unless rule_set.test(input)
105
+ result = false
106
+ end
107
+
108
+ end
109
+ end
110
+
111
+ return result
112
+
113
+ end
114
+
115
+ ##
116
+ # Validate output.
117
+ #
118
+ # @stage Called when validating a reflection.
119
+ # @param output [Dynamic] The method's return value.
120
+ # @param output_rule_set [RuleSet] The RuleSet to validate the output with.
121
+ ##
122
+ def test_output(output, output_rule_set)
123
+
124
+ # Default to a PASS result.
125
+ result = true
126
+
127
+ unless output_rule_set.nil?
128
+
129
+ # Validate output RuleSet for that argument.
130
+ unless output_rule_set.test(output)
131
+ result = false
132
+ end
133
+
134
+ end
135
+
136
+ return result
137
+
138
+ end
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
+
251
+ end
@@ -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
@@ -0,0 +1,42 @@
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 execution path.
35
+ @output_path = nil
36
+
37
+ # Name of output directory.
38
+ @output_directory = "reflections"
39
+
40
+ end
41
+
42
+ end
@@ -1,31 +1,79 @@
1
+ ################################################################################
2
+ # A shapshot of real data.
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
+ #
10
+ # @hierachy
11
+ # 1. Execution
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
+
1
21
  require 'Reflection'
22
+ require 'MetaBuilder'
2
23
 
3
24
  class Control < Reflection
4
25
 
5
26
  ##
6
27
  # Reflect on a method.
7
28
  #
8
- # Creates a shadow execution stack.
9
- #
10
- # @param method - The name of the method.
11
- # @param *args - The method arguments.
12
- #
13
- # @return - A reflection hash.
29
+ # Creates a shadow execution.
30
+ # @param *args [Dynamic] The method's arguments.
14
31
  ##
15
32
  def reflect(*args)
16
33
 
17
- @inputs = *args
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
50
+
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)
18
54
 
19
- # Action method with new arguments.
55
+ end
56
+
57
+ # Action method with new/old arguments.
20
58
  begin
21
- @output = @clone.send(@method, *@inputs)
22
- # When fail.
59
+
60
+ # Run reflection.
61
+ output = @clone.send(@method, *args)
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.
23
72
  rescue StandardError => message
24
- @status = :fail
73
+
74
+ @status = :error
25
75
  @message = message
26
- # When pass.
27
- else
28
- @status = :pass
76
+
29
77
  end
30
78
 
31
79
  end