reflekt 0.9.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2048b61fdb7acc0deede9ee5bcae644e6d51fa6e2dab2842f748433ce5ba949
4
- data.tar.gz: dce2b1bd92e2eaf90c16e1cad6c27d9b9fc686001c958124f184a5d11a2ebe8d
3
+ metadata.gz: e94e86e6d558012df59e1aebfdbbb7c2bf70a2e849e9a186795a3e4d5cb648f0
4
+ data.tar.gz: 9db428f6c518c06fbddb83e0abd9920b9dc30344846827b5c9505c3f2bc111c9
5
5
  SHA512:
6
- metadata.gz: b4bdebf8083aef0a50806c1970b25f90736dfe68b8373f5a742ef6c7f2e4139e4ca0d273d683d826230069de2039c5fda7428c4ed8147471da00f1e93704f59a
7
- data.tar.gz: afbe22e05eb10efe8ead84240c4296546e10570c19e73efea912494e55a85538c8fbed2872c42485ea21ba696a101347e73ec5feee37a568636a154dcae8bcf6
6
+ metadata.gz: e2a7ecf3adb9e06f7f3a09d507265c035bf3c641193711c64fea512b03973696c8ef9278d59eedf43ee83dd03a0f5f552026f0b2f6ba6182c6361bb35a211bf7
7
+ data.tar.gz: f002c69e490b63dd065e5f0ba0b40e9dcbbe980f71e7df66da01b1bc37b2dfe1081c9e58a3024b388b96628cc98422875a5b90f1e9227327f3241bc5d61450b0
@@ -1,36 +1,36 @@
1
1
  ################################################################################
2
- # ACCESSOR
2
+ # Access variables via one object to avoid polluting the caller class scope.
3
3
  #
4
- # Access variables via one object to avoid polluting the caller class.
4
+ # @pattern Singleton
5
5
  #
6
- # Only 2 variables are not accessed via Accessor:
7
- # - @reflection_counts on the instance
6
+ # @note Some variables are not accessed via Accessor:
7
+ # - @reflekt_counts on the instance
8
8
  # - @@reflekt_skipped_methods on the instance's singleton class
9
9
  ################################################################################
10
10
 
11
11
  class Accessor
12
12
 
13
+ attr_accessor :config
13
14
  attr_accessor :setup
14
15
  attr_accessor :db
15
16
  attr_accessor :stack
17
+ attr_accessor :aggregator
16
18
  attr_accessor :renderer
17
- attr_accessor :rules
18
19
  attr_accessor :path
19
20
  attr_accessor :output_path
20
- attr_accessor :reflect_amount
21
- attr_accessor :reflection_limit
21
+ attr_accessor :error
22
22
 
23
23
  def initialize()
24
24
 
25
+ @config = nil
25
26
  @setup = nil
26
27
  @db = nil
27
28
  @stack = nil
29
+ @aggregator = nil
28
30
  @renderer = nil
29
- @rules = nil
30
31
  @path = nil
31
32
  @output_path = nil
32
- @reflect_amount = nil
33
- @reflection_limit = nil
33
+ @error = false
34
34
 
35
35
  end
36
36
 
@@ -0,0 +1,238 @@
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
+ # TODO: Remove once "Fix Rowdb.get(path)" bug fixed.
53
+ meta = meta.transform_keys(&:to_sym)
54
+ # Deserialize meta type to symbol.
55
+ meta[:type] = meta[:type].to_sym
56
+
57
+ # Get rule set.
58
+ rule_set = get_input_rule_set(klass, method, arg_num)
59
+ if rule_set.nil?
60
+ rule_set = RuleSet.new(@meta_map)
61
+ set_input_rule_set(klass, method, arg_num, rule_set)
62
+ end
63
+
64
+ # Train on metadata.
65
+ rule_set.train(meta)
66
+
67
+ end
68
+ end
69
+
70
+ ##
71
+ # OUTPUT
72
+ ##
73
+
74
+ # Get rule set.
75
+ output_rule_set = get_output_rule_set(klass, method)
76
+ if output_rule_set.nil?
77
+ output_rule_set = RuleSet.new(@meta_map)
78
+ set_output_rule_set(klass, method, output_rule_set)
79
+ end
80
+
81
+ # Train on metadata.
82
+ output_rule_set.train(control["output"])
83
+
84
+ end
85
+
86
+ end
87
+
88
+ ##
89
+ # Validate inputs.
90
+ #
91
+ # @stage Called when validating a reflection.
92
+ # @param inputs [Array] The method's arguments.
93
+ # @param input_rule_sets [Array] The RuleSets to validate each input with.
94
+ ##
95
+ def test_inputs(inputs, input_rule_sets)
96
+
97
+ # Default result to PASS.
98
+ result = true
99
+
100
+ # Validate each argument against each rule set for that argument.
101
+ inputs.each_with_index do |input, arg_num|
102
+
103
+ unless input_rule_sets[arg_num].nil?
104
+
105
+ rule_set = input_rule_sets[arg_num]
106
+
107
+ unless rule_set.test(input)
108
+ result = false
109
+ end
110
+
111
+ end
112
+ end
113
+
114
+ return result
115
+
116
+ end
117
+
118
+ ##
119
+ # Validate output.
120
+ #
121
+ # @stage Called when validating a reflection.
122
+ # @param output [Dynamic] The method's return value.
123
+ # @param output_rule_set [RuleSet] The RuleSet to validate the output with.
124
+ ##
125
+ def test_output(output, output_rule_set)
126
+
127
+ # Default to a PASS result.
128
+ result = true
129
+
130
+ unless output_rule_set.nil?
131
+
132
+ # Validate output RuleSet for that argument.
133
+ unless output_rule_set.test(output)
134
+ result = false
135
+ end
136
+
137
+ end
138
+
139
+ return result
140
+
141
+ end
142
+
143
+ ##
144
+ # Get aggregated RuleSets for all inputs.
145
+ #
146
+ # @stage Called when building a reflection.
147
+ # @param klass [Symbol]
148
+ # @param method [Symbol]
149
+ # @return [Array]
150
+ ##
151
+ def get_input_rule_sets(klass, method)
152
+ @rule_sets.dig(klass, method, :inputs)
153
+ end
154
+
155
+ ##
156
+ # Get an aggregated RuleSet for an output.
157
+ #
158
+ # @stage Called when building a reflection.
159
+ # @param klass [Symbol]
160
+ # @param method [Symbol]
161
+ # @return [RuleSet]
162
+ ##
163
+ def get_output_rule_set(klass, method)
164
+ @rule_sets.dig(klass, method, :output)
165
+ end
166
+
167
+ ##
168
+ # Get the base rule type for a data type.
169
+ ##
170
+ def self.value_to_rule_type(value)
171
+
172
+ data_type = value.class
173
+
174
+ rule_types = {
175
+ Array => ArrayRule,
176
+ TrueClass => BooleanRule,
177
+ FalseClass => BooleanRule,
178
+ Float => FloatRule,
179
+ Integer => IntegerRule,
180
+ String => StringRule
181
+ }
182
+
183
+ return rule_types[data_type]
184
+
185
+ end
186
+
187
+ ##############################################################################
188
+ # HELPERS
189
+ ##############################################################################
190
+
191
+ private
192
+
193
+ ##
194
+ # Get an aggregated RuleSet for an input.
195
+ #
196
+ # @param klass [Symbol]
197
+ # @param method [Symbol]
198
+ # @return [RuleSet]
199
+ ##
200
+ def get_input_rule_set(klass, method, arg_num)
201
+ @rule_sets.dig(klass, method, :inputs, arg_num)
202
+ end
203
+
204
+ ##
205
+ # Set an aggregated RuleSet for an input.
206
+ #
207
+ # @param klass [Symbol]
208
+ # @param method [Symbol]
209
+ ##
210
+ def set_input_rule_set(klass, method, arg_num, rule_set)
211
+
212
+ # Set defaults.
213
+ @rule_sets[klass] = {} unless @rule_sets.key? klass
214
+ @rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
215
+ @rule_sets[klass][method][:inputs] = [] unless @rule_sets[klass][method].key? :inputs
216
+ # Set value.
217
+ @rule_sets[klass][method][:inputs][arg_num] = rule_set
218
+
219
+ end
220
+
221
+ ##
222
+ # Set an aggregated RuleSet for an output.
223
+ #
224
+ # @param klass [Symbol]
225
+ # @param method [Symbol]
226
+ # @param rule_set [RuleSet]
227
+ ##
228
+ def set_output_rule_set(klass, method, rule_set)
229
+
230
+ # Set defaults.
231
+ @rule_sets[klass] = {} unless @rule_sets.key? klass
232
+ @rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
233
+ # Set value.
234
+ @rule_sets[klass][method][:output] = rule_set
235
+
236
+ end
237
+
238
+ 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,41 @@
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
+ :string => [StringRule]
30
+ }
31
+
32
+ # An absolute path to the directory that contains the output directory.
33
+ # Defaults to current execution path.
34
+ @output_path = nil
35
+
36
+ # Name of output directory.
37
+ @output_directory = "reflections"
38
+
39
+ end
40
+
41
+ end
@@ -1,31 +1,70 @@
1
+ ################################################################################
2
+ # A shapshot of real data.
3
+ #
4
+ # A control's @number property will always be zero.
5
+ #
6
+ # @hierachy
7
+ # 1. Execution
8
+ # 2. Control <- YOU ARE HERE
9
+ # 3. Meta
10
+ ################################################################################
11
+
1
12
  require 'Reflection'
13
+ require 'MetaBuilder'
2
14
 
3
15
  class Control < Reflection
4
16
 
5
17
  ##
6
18
  # Reflect on a method.
7
19
  #
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.
20
+ # Creates a shadow execution.
21
+ # @param *args [Dynamic] The method's arguments.
14
22
  ##
15
23
  def reflect(*args)
16
24
 
17
- @inputs = *args
25
+ # Get aggregated rule sets.
26
+ input_rule_sets = @aggregator.get_input_rule_sets(@klass, @method)
27
+ output_rule_set = @aggregator.get_output_rule_set(@klass, @method)
28
+
29
+ # When arguments exist.
30
+ unless args.size == 0
31
+
32
+ # When aggregated rule sets exist.
33
+ unless input_rule_sets.nil?
34
+
35
+ # Validate arguments against aggregated rule sets.
36
+ unless @aggregator.test_inputs(args, input_rule_sets)
37
+ @status = :fail
38
+ end
39
+
40
+ end
41
+
42
+ # Create metadata for each argument.
43
+ # TODO: Create metadata for other inputs such as properties on the instance.
44
+ @inputs = MetaBuilder.create_many(args)
18
45
 
19
- # Action method with new arguments.
46
+ end
47
+
48
+ # Action method with new/old arguments.
20
49
  begin
21
- @output = @clone.send(@method, *@inputs)
22
- # When fail.
50
+
51
+ # Run reflection.
52
+ output = @clone.send(@method, *args)
53
+ @output = MetaBuilder.create(output)
54
+
55
+ # Validate output with aggregated control rule sets.
56
+ unless output_rule_set.nil?
57
+ unless @aggregator.test_output(output, output_rule_set)
58
+ @status = :fail
59
+ end
60
+ end
61
+
62
+ # When a system error occurs.
23
63
  rescue StandardError => message
24
- @status = FAIL
64
+
65
+ @status = :error
25
66
  @message = message
26
- # When pass.
27
- else
28
- @status = PASS
67
+
29
68
  end
30
69
 
31
70
  end