reflekt 0.9.8 → 1.0.3

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: c5b9e88d60fea03ebe06c430b489cb1295b8d56ec76f30982721a709a406f0af
4
- data.tar.gz: 948f53a8b72f5befda3e175029edfdb017d98b3b8fd41998ab95b5f6b0a6b95e
3
+ metadata.gz: d09b97f103669d2806a5c6e32da41e978fecff763c558d5aa8fb0739bf8e984a
4
+ data.tar.gz: 5f40bbfaa6444d452a0f91c1371d0d9aa75a5cd7edd5da8e36ac81d7f0c7532d
5
5
  SHA512:
6
- metadata.gz: e70f287d10e70e3ac8ab3e01881ed6d8bb79f881c9af5530f39c7dd29997021ddf246d1129467503cfb3c6efb0589604648876c64bda917e8b970cb278a79fb3
7
- data.tar.gz: ef005f855d7c3d1002eb059a73ecf742645841d4d3d0bd416a84b549e2e7d5b63a8bc216e8fe1404bf20c383a8e0a10c54740458e40382fa9591f9c67f3a075c
6
+ metadata.gz: c7198d5f60ee546e1becc9e7e75141705b0f4a01214e70bba2ba597872b2ff7dbd0cd60deb877a18fde3b4c25ba48ce94bede291bd9ddc089c3d195710dd5728
7
+ data.tar.gz: 23b79441dfa54881f1a537d259f686b8528f950aa1caac960c43403d7f5f24301a903ba99cc84d7bf1e743f6f6e16001141cff40a8c70139bf55032f38193131
@@ -2,14 +2,15 @@
2
2
  # Access variables via one object to avoid polluting the caller class scope.
3
3
  #
4
4
  # @pattern Singleton
5
+ #
5
6
  # @note Some variables are not accessed via Accessor:
6
7
  # - @reflekt_counts on the instance
7
- # - @reflekt_enabled 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,11 +18,11 @@ class Accessor
17
18
  attr_accessor :renderer
18
19
  attr_accessor :path
19
20
  attr_accessor :output_path
20
- attr_accessor :reflect_amount
21
- attr_accessor :reflect_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,8 +30,7 @@ class Accessor
29
30
  @renderer = nil
30
31
  @path = nil
31
32
  @output_path = nil
32
- @reflect_amount = nil
33
- @reflect_limit = nil
33
+ @error = false
34
34
 
35
35
  end
36
36
 
@@ -1,11 +1,11 @@
1
1
  ################################################################################
2
- # Aggregate reflection metadata into rule sets.
3
- # Validate reflection arguments against aggregates.
2
+ # Aggregate control metadata into rule sets.
3
+ # Validate reflections against aggregated controls.
4
4
  #
5
5
  # @pattern Singleton
6
6
  #
7
7
  # @hierachy
8
- # 1. Aggregator
8
+ # 1. Aggregator <- YOU ARE HERE
9
9
  # 2. RuleSet
10
10
  # 3. Rule
11
11
  ################################################################################
@@ -14,102 +14,47 @@ require 'RuleSet'
14
14
 
15
15
  class Aggregator
16
16
 
17
- def initialize()
18
-
19
- # Key rule sets by class and method.
20
- @rule_sets = {}
21
-
22
- end
23
-
24
- ##
25
- # Get aggregated RuleSets for all inputs.
26
- #
27
- # @param klass [Symbol]
28
- # @param method [Symbol]
29
- # @return [Array]
30
- ##
31
- def get_input_rule_sets(klass, method)
32
- return @rule_sets.dig(klass, method, :inputs)
33
- end
34
-
35
- ##
36
- # Get an aggregated RuleSet for an input.
37
- #
38
- # @param klass [Symbol]
39
- # @param method [Symbol]
40
- # @return [RuleSet]
41
17
  ##
42
- def get_input_rule_set(klass, method, arg_num)
43
- @rule_sets.dig(klass, method, :inputs, arg_num)
44
- end
45
-
18
+ # @param meta_map [Hash] The rules that apply to each meta type.
46
19
  ##
47
- # Get an aggregated RuleSet for an output.
48
- #
49
- # @param klass [Symbol]
50
- # @param method [Symbol]
51
- # @return [RuleSet]
52
- ##
53
- def get_output_rule_set(klass, method)
54
- @rule_sets.dig(klass, method, :output)
55
- end
20
+ def initialize(meta_map)
56
21
 
57
- ##
58
- # Set an aggregated RuleSet for an input.
59
- #
60
- # @param klass [Symbol]
61
- # @param method [Symbol]
62
- ##
63
- def set_input_rule_set(klass, method, arg_num, rule_set)
64
- # Set defaults.
65
- @rule_sets[klass] = {} unless @rule_sets.key? klass
66
- @rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
67
- @rule_sets[klass][method][:inputs] = [] unless @rule_sets[klass][method].key? :inputs
68
- # Set value.
69
- @rule_sets[klass][method][:inputs][arg_num] = rule_set
70
- end
22
+ @meta_map = meta_map
23
+ # Key rule sets by class and method.
24
+ @rule_sets = {}
71
25
 
72
- ##
73
- # Set an aggregated RuleSet for an output.
74
- #
75
- # @param klass [Symbol]
76
- # @param method [Symbol]
77
- # @param rule_set [RuleSet]
78
- ##
79
- def set_output_rule_set(klass, method, rule_set)
80
- # Set defaults.
81
- @rule_sets[klass] = {} unless @rule_sets.key? klass
82
- @rule_sets[klass][method] = {} unless @rule_sets[klass].key? method
83
- # Set value.
84
- @rule_sets[klass][method][:output] = rule_set
85
26
  end
86
27
 
87
28
  ##
88
- # Create aggregated rule sets from reflection metadata.
29
+ # Create aggregated rule sets from control metadata.
89
30
  #
90
- # @param reflections [Array] Controls with metadata.
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.
91
34
  ##
92
- def train(reflections)
35
+ def train(controls)
93
36
 
94
- # On first use there are no previous reflections.
95
- return if reflections.nil?
37
+ # On first use there are no previous controls.
38
+ return if controls.nil?
96
39
 
97
- reflections.each do |reflection|
40
+ controls.each do |control|
98
41
 
99
- klass = reflection[:class]
100
- method = reflection[:method]
42
+ klass = control["class"].to_sym
43
+ method = control["method"].to_sym
101
44
 
102
45
  ##
103
46
  # INPUT
104
47
  ##
105
48
 
106
- unless reflection[:inputs].nil?
107
- reflection[:inputs].each_with_index do |meta, arg_num|
49
+ unless control["inputs"].nil?
50
+ control["inputs"].each_with_index do |meta, arg_num|
51
+
52
+ meta = Meta.deserialize(meta)
108
53
 
109
54
  # Get rule set.
110
55
  rule_set = get_input_rule_set(klass, method, arg_num)
111
56
  if rule_set.nil?
112
- rule_set = RuleSet.new()
57
+ rule_set = RuleSet.new(@meta_map)
113
58
  set_input_rule_set(klass, method, arg_num, rule_set)
114
59
  end
115
60
 
@@ -126,12 +71,12 @@ class Aggregator
126
71
  # Get rule set.
127
72
  output_rule_set = get_output_rule_set(klass, method)
128
73
  if output_rule_set.nil?
129
- output_rule_set = RuleSet.new()
74
+ output_rule_set = RuleSet.new(@meta_map)
130
75
  set_output_rule_set(klass, method, output_rule_set)
131
76
  end
132
77
 
133
78
  # Train on metadata.
134
- output_rule_set.train(reflection[:output])
79
+ output_rule_set.train(Meta.deserialize(control["output"]))
135
80
 
136
81
  end
137
82
 
@@ -140,22 +85,23 @@ class Aggregator
140
85
  ##
141
86
  # Validate inputs.
142
87
  #
88
+ # @stage Called when validating a reflection.
143
89
  # @param inputs [Array] The method's arguments.
144
90
  # @param input_rule_sets [Array] The RuleSets to validate each input with.
145
91
  ##
146
- def validate_inputs(inputs, input_rule_sets)
92
+ def test_inputs(inputs, input_rule_sets)
147
93
 
148
- # Default to a PASS result.
94
+ # Default result to PASS.
149
95
  result = true
150
96
 
151
- # Validate each argument against each RuleSet for that argument.
97
+ # Validate each argument against each rule set for that argument.
152
98
  inputs.each_with_index do |input, arg_num|
153
99
 
154
100
  unless input_rule_sets[arg_num].nil?
155
101
 
156
102
  rule_set = input_rule_sets[arg_num]
157
103
 
158
- unless rule_set.validate_rule(input)
104
+ unless rule_set.test(input)
159
105
  result = false
160
106
  end
161
107
 
@@ -169,10 +115,11 @@ class Aggregator
169
115
  ##
170
116
  # Validate output.
171
117
  #
118
+ # @stage Called when validating a reflection.
172
119
  # @param output [Dynamic] The method's return value.
173
120
  # @param output_rule_set [RuleSet] The RuleSet to validate the output with.
174
121
  ##
175
- def validate_output(output, output_rule_set)
122
+ def test_output(output, output_rule_set)
176
123
 
177
124
  # Default to a PASS result.
178
125
  result = true
@@ -180,7 +127,7 @@ class Aggregator
180
127
  unless output_rule_set.nil?
181
128
 
182
129
  # Validate output RuleSet for that argument.
183
- unless output_rule_set.validate_rule(output)
130
+ unless output_rule_set.test(output)
184
131
  result = false
185
132
  end
186
133
 
@@ -190,4 +137,115 @@ class Aggregator
190
137
 
191
138
  end
192
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
+
193
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,10 +1,21 @@
1
1
  ################################################################################
2
2
  # A shapshot of real data.
3
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
+ #
4
10
  # @hierachy
5
11
  # 1. Execution
6
- # 2. Control
7
- # 3. RuleSet
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.
8
19
  ################################################################################
9
20
 
10
21
  require 'Reflection'
@@ -15,27 +26,54 @@ class Control < Reflection
15
26
  ##
16
27
  # Reflect on a method.
17
28
  #
18
- # Creates a shadow execution stack.
19
- #
20
- # @param method [Symbol] The name of the method.
21
- # @param *args [Args] The method arguments.
22
- # @return [Hash] A reflection hash.
29
+ # Creates a shadow execution.
30
+ # @param *args [Dynamic] The method's arguments.
23
31
  ##
24
32
  def reflect(*args)
25
33
 
26
- # Create metadata for each argument.
27
- @inputs = MetaBuilder.create_many(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
28
50
 
29
- # Action method with new arguments.
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)
54
+
55
+ end
56
+
57
+ # Action method with new/old arguments.
30
58
  begin
59
+
60
+ # Run reflection.
31
61
  output = @clone.send(@method, *args)
32
- # When fail.
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.
33
72
  rescue StandardError => message
34
- @status = :fail
73
+
74
+ @status = :error
35
75
  @message = message
36
- # When pass.
37
- else
38
- @status = :pass
76
+
39
77
  end
40
78
 
41
79
  end