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 +4 -4
- data/lib/Accessor.rb +5 -5
- data/lib/Aggregator.rb +144 -86
- data/lib/Clone.rb +31 -0
- data/lib/Config.rb +42 -0
- data/lib/Control.rb +53 -15
- data/lib/Execution.rb +15 -6
- data/lib/Meta.rb +48 -4
- data/lib/MetaBuilder.rb +34 -6
- data/lib/Reflection.rb +73 -38
- data/lib/Reflekt.rb +104 -66
- data/lib/Rule.rb +19 -3
- data/lib/RuleSet.rb +59 -55
- data/lib/ShadowStack.rb +2 -0
- data/lib/meta/ArrayMeta.rb +34 -0
- data/lib/meta/BooleanMeta.rb +26 -0
- data/lib/meta/FloatMeta.rb +26 -0
- data/lib/meta/IntegerMeta.rb +3 -4
- data/lib/meta/NullMeta.rb +34 -0
- data/lib/meta/StringMeta.rb +4 -5
- data/lib/rules/ArrayRule.rb +88 -0
- data/lib/rules/BooleanRule.rb +47 -0
- data/lib/rules/FloatRule.rb +57 -0
- data/lib/rules/IntegerRule.rb +8 -2
- data/lib/rules/NullRule.rb +36 -0
- data/lib/rules/StringRule.rb +26 -2
- data/lib/web/README.md +3 -3
- data/lib/web/bundle.js +5 -5
- data/lib/web/server.js +45 -49
- metadata +16 -6
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d09b97f103669d2806a5c6e32da41e978fecff763c558d5aa8fb0739bf8e984a
         | 
| 4 | 
            +
              data.tar.gz: 5f40bbfaa6444d452a0f91c1371d0d9aa75a5cd7edd5da8e36ac81d7f0c7532d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c7198d5f60ee546e1becc9e7e75141705b0f4a01214e70bba2ba597872b2ff7dbd0cd60deb877a18fde3b4c25ba48ce94bede291bd9ddc089c3d195710dd5728
         | 
| 7 | 
            +
              data.tar.gz: 23b79441dfa54881f1a537d259f686b8528f950aa1caac960c43403d7f5f24301a903ba99cc84d7bf1e743f6f6e16001141cff40a8c70139bf55032f38193131
         | 
    
        data/lib/Accessor.rb
    CHANGED
    
    | @@ -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 : | 
| 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 | 
            -
                @ | 
| 33 | 
            -
                @reflect_limit = nil
         | 
| 33 | 
            +
                @error = false
         | 
| 34 34 |  | 
| 35 35 | 
             
              end
         | 
| 36 36 |  | 
    
        data/lib/Aggregator.rb
    CHANGED
    
    | @@ -1,11 +1,11 @@ | |
| 1 1 | 
             
            ################################################################################
         | 
| 2 | 
            -
            # Aggregate  | 
| 3 | 
            -
            # Validate  | 
| 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 | 
            -
               | 
| 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 | 
            -
               | 
| 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 | 
            -
             | 
| 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  | 
| 29 | 
            +
              # Create aggregated rule sets from control metadata.
         | 
| 89 30 | 
             
              #
         | 
| 90 | 
            -
              # @ | 
| 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( | 
| 35 | 
            +
              def train(controls)
         | 
| 93 36 |  | 
| 94 | 
            -
                # On first use there are no previous  | 
| 95 | 
            -
                return if  | 
| 37 | 
            +
                # On first use there are no previous controls.
         | 
| 38 | 
            +
                return if controls.nil?
         | 
| 96 39 |  | 
| 97 | 
            -
                 | 
| 40 | 
            +
                controls.each do |control|
         | 
| 98 41 |  | 
| 99 | 
            -
                  klass =  | 
| 100 | 
            -
                  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  | 
| 107 | 
            -
                     | 
| 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( | 
| 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  | 
| 92 | 
            +
              def test_inputs(inputs, input_rule_sets)
         | 
| 147 93 |  | 
| 148 | 
            -
                # Default to  | 
| 94 | 
            +
                # Default result to PASS.
         | 
| 149 95 | 
             
                result = true
         | 
| 150 96 |  | 
| 151 | 
            -
                # Validate each argument against each  | 
| 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. | 
| 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  | 
| 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. | 
| 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
         | 
    
        data/lib/Clone.rb
    ADDED
    
    | @@ -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
         | 
    
        data/lib/Config.rb
    ADDED
    
    | @@ -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
         | 
    
        data/lib/Control.rb
    CHANGED
    
    | @@ -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.  | 
| 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 | 
| 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 | 
            -
                #  | 
| 27 | 
            -
                 | 
| 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 | 
            -
             | 
| 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 | 
            -
             | 
| 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 | 
            -
             | 
| 73 | 
            +
             | 
| 74 | 
            +
                  @status = :error
         | 
| 35 75 | 
             
                  @message = message
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                else
         | 
| 38 | 
            -
                  @status = :pass
         | 
| 76 | 
            +
             | 
| 39 77 | 
             
                end
         | 
| 40 78 |  | 
| 41 79 | 
             
              end
         |