reflekt 0.9.6 → 1.0.1

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: 30e9de1f6073eb71a87871e5790dee7a5da6476b4c787a31c75d772986994295
4
- data.tar.gz: 29b671194ac45fe98d596c4aefcd7cb17a5aba511d82109968403889d7d94aef
3
+ metadata.gz: cfaf70b43c12867f93934b6b1f2e0d672486b3331369c9c85c0646e54bfc18d2
4
+ data.tar.gz: 437bbcdd66ae77ec202360255386edc10d69bcfb2da5b41816b0aed3c3151285
5
5
  SHA512:
6
- metadata.gz: b3701e103b4ad81c7f1e0697b5f1dd07075f7fc8f55cc1715a0e9d2b8448218b8f8c6efa3ef6334943ba369172d967879b0e9e7516b1b0e2652981147ca4f107
7
- data.tar.gz: 278a84e1cb673170c52779aea32de1e958b1ea2f2b24dcc6cb8c1356603b07d018c4d2ff22d16b9a86f2ea03beee8462f5024be87d94c362ff5163418259234a
6
+ metadata.gz: 789f134df80a4cb9455274cd36d968f83903f6c474b6974d451ecfea1910799121f815eeecb9162a3b0ea2417f52983f1bb4557a5dd9b729fbdfa3e7325a6b99
7
+ data.tar.gz: 3bfb838fb97dda4989fba353db654b9498ce2ff8112f880d0bb5c926ae58865e05916701ec81cf393486b0b279af308a349245c970242879774c172bf12e2e7c
@@ -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,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