reflekt 0.9.8 → 0.9.9

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: c5b9e88d60fea03ebe06c430b489cb1295b8d56ec76f30982721a709a406f0af
4
- data.tar.gz: 948f53a8b72f5befda3e175029edfdb017d98b3b8fd41998ab95b5f6b0a6b95e
3
+ metadata.gz: f04cedc3780f61776191bf7ae72822aae50eba606c76c61c176f5c252462fa22
4
+ data.tar.gz: 2ca6aa88016bfcab50460048d338a45f3855ee623f1b1bb5edc5e36323418eca
5
5
  SHA512:
6
- metadata.gz: e70f287d10e70e3ac8ab3e01881ed6d8bb79f881c9af5530f39c7dd29997021ddf246d1129467503cfb3c6efb0589604648876c64bda917e8b970cb278a79fb3
7
- data.tar.gz: ef005f855d7c3d1002eb059a73ecf742645841d4d3d0bd416a84b549e2e7d5b63a8bc216e8fe1404bf20c383a8e0a10c54740458e40382fa9591f9c67f3a075c
6
+ metadata.gz: 88024a7b33ba0ac0fca948b1b0808ad1a7094e958ae3b5d48f378b2c9256fcb29735b4635880322f5c2ee62e0034a265263997c3074d90d6756aef5408e5a2cb
7
+ data.tar.gz: b2700bb56c2cf3915676c797381ad7913cb3091ffe576e7f276c9e97dcde488be602e01defbd812c3886f26a2cdde4090bd207312bad14f3d1ab20e55e3541e6
@@ -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,10 @@ 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
22
21
 
23
22
  def initialize()
24
23
 
24
+ @config = nil
25
25
  @setup = nil
26
26
  @db = nil
27
27
  @stack = nil
@@ -29,8 +29,6 @@ class Accessor
29
29
  @renderer = nil
30
30
  @path = nil
31
31
  @output_path = nil
32
- @reflect_amount = nil
33
- @reflect_limit = nil
34
32
 
35
33
  end
36
34
 
@@ -5,7 +5,7 @@
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,8 +14,12 @@ require 'RuleSet'
14
14
 
15
15
  class Aggregator
16
16
 
17
- def initialize()
17
+ ##
18
+ # @param meta_map [Hash] The rules that apply to each meta type.
19
+ ##
20
+ def initialize(meta_map)
18
21
 
22
+ @meta_map = meta_map
19
23
  # Key rule sets by class and method.
20
24
  @rule_sets = {}
21
25
 
@@ -109,7 +113,7 @@ class Aggregator
109
113
  # Get rule set.
110
114
  rule_set = get_input_rule_set(klass, method, arg_num)
111
115
  if rule_set.nil?
112
- rule_set = RuleSet.new()
116
+ rule_set = RuleSet.new(@meta_map)
113
117
  set_input_rule_set(klass, method, arg_num, rule_set)
114
118
  end
115
119
 
@@ -126,7 +130,7 @@ class Aggregator
126
130
  # Get rule set.
127
131
  output_rule_set = get_output_rule_set(klass, method)
128
132
  if output_rule_set.nil?
129
- output_rule_set = RuleSet.new()
133
+ output_rule_set = RuleSet.new(@meta_map)
130
134
  set_output_rule_set(klass, method, output_rule_set)
131
135
  end
132
136
 
@@ -0,0 +1,35 @@
1
+ class Config
2
+
3
+ attr_accessor :reflect_amount
4
+ attr_accessor :reflect_limit
5
+ attr_accessor :meta_map
6
+ attr_accessor :output_path
7
+ attr_accessor :output_directory
8
+
9
+ def initialize()
10
+
11
+ # The amount of reflections to create per method call.
12
+ @reflect_amount = 2
13
+
14
+ # The maximum amount of reflections that can be created per instance/method.
15
+ # A method called thousands of times doesn't need that many reflections.
16
+ @reflect_limit = 10
17
+
18
+ # The rules that apply to meta types.
19
+ @meta_map = {
20
+ :array => [ArrayRule],
21
+ :bool => [BooleanRule],
22
+ :int => [IntegerRule],
23
+ :string => [StringRule]
24
+ }
25
+
26
+ # An absolute path to the directory that contains the output directory.
27
+ # Defaults to current execution path.
28
+ @output_path = nil
29
+
30
+ # Name of output directory.
31
+ @output_directory = "reflections"
32
+
33
+ end
34
+
35
+ end
@@ -17,10 +17,10 @@ class Execution
17
17
  ##
18
18
  # Create Execution.
19
19
  #
20
- # @param Object object - The calling object.
21
- # @param Symbol method - The calling method.
22
- # @param Integer number - The number of reflections to create per execution.
23
- # @param ShadowStack stack - The shadow execution call stack.
20
+ # @param object [Object] The calling object.
21
+ # @param method [Symbol] The calling method.
22
+ # @param number [Integer] The number of reflections to create per execution.
23
+ # @param stack [ShadowStack] The shadow execution call stack.
24
24
  ##
25
25
  def initialize(caller_object, method, number, stack)
26
26
 
@@ -1,7 +1,7 @@
1
1
  ################################################################################
2
- # Meta for input and output. All meta behave the same.
2
+ # Metadata for input and output.
3
3
  #
4
- # @pattern Abstract class.
4
+ # @pattern Abstract class
5
5
  # @see lib/meta for each meta.
6
6
  ################################################################################
7
7
 
@@ -1,7 +1,7 @@
1
1
  ################################################################################
2
- # Create Meta.
2
+ # Create metadata.
3
3
  #
4
- # @pattern Builder.
4
+ # @pattern Builder
5
5
  # @see lib/meta for each meta.
6
6
  ################################################################################
7
7
 
@@ -1,14 +1,15 @@
1
1
  ################################################################################
2
2
  # Reflective testing.
3
3
  #
4
- # @author
5
- # Maedi Prichard
4
+ # @author Maedi Prichard
6
5
  #
7
6
  # @flow
8
- # 1. An Execution is created on method call.
9
- # 2. Many Refections are created per Execution.
10
- # 3. Each Reflection executes on cloned data.
11
- # 4. Flow is returned to the original method.
7
+ # 1. Reflekt is prepended to a class and setup.
8
+ # 2. When a class insantiates so does Reflekt.
9
+ # 3. An Execution is created on method call.
10
+ # 4. Many Refections are created per Execution.
11
+ # 5. Each Reflection executes on cloned data.
12
+ # 6. Flow is returned to the original method.
12
13
  #
13
14
  # @usage
14
15
  # class ExampleClass
@@ -20,11 +21,14 @@ require 'erb'
20
21
  require 'rowdb'
21
22
  require 'Accessor'
22
23
  require 'Aggregator'
24
+ require 'Config'
23
25
  require 'Control'
24
26
  require 'Execution'
25
27
  require 'Reflection'
26
28
  require 'Renderer'
27
29
  require 'ShadowStack'
30
+ # Require all rules.
31
+ Dir[File.join(__dir__, 'rules', '*.rb')].each { |file| require file }
28
32
 
29
33
  module Reflekt
30
34
 
@@ -32,37 +36,41 @@ module Reflekt
32
36
 
33
37
  @reflekt_counts = {}
34
38
 
35
- # Get instance methods.
36
- # TODO: Include parent methods like "Array.include?".
37
- self.class.instance_methods(false).each do |method|
39
+ # Get child and parent instance methods.
40
+ parent_instance_methods = self.class.superclass.instance_methods(false)
41
+ child_instance_methods = self.class.instance_methods(false)
42
+ instance_methods = parent_instance_methods + child_instance_methods
38
43
 
39
- # Don't process skipped methods.
40
- next if self.class.reflekt_skipped?(method)
44
+ # TODO: Include core methods like "Array.include?".
45
+ instance_methods.each do |method|
41
46
 
42
47
  @reflekt_counts[method] = 0
43
48
 
44
49
  # When method called in flow.
45
50
  self.define_singleton_method(method) do |*args|
46
51
 
47
- # Don't reflect when limit reached.
48
- unless @reflekt_counts[method] >= @@reflekt.reflect_limit
52
+ # Get current execution.
53
+ execution = @@reflekt.stack.peek()
49
54
 
50
- # Get current execution.
51
- execution = @@reflekt.stack.peek()
55
+ # Don't reflect when reflect limit reached or method skipped.
56
+ unless (@reflekt_counts[method] >= @@reflekt.config.reflect_limit) || self.class.reflekt_skipped?(method)
52
57
 
53
58
  # When stack empty or past execution done reflecting.
54
59
  if execution.nil? || execution.has_finished_reflecting?
55
60
 
56
61
  # Create execution.
57
- execution = Execution.new(self, method, @@reflekt.reflect_amount, @@reflekt.stack)
62
+ execution = Execution.new(self, method, @@reflekt.config.reflect_amount, @@reflekt.stack)
58
63
 
59
64
  @@reflekt.stack.push(execution)
60
65
 
61
66
  end
62
67
 
63
- # Reflect.
68
+ ##
69
+ # Reflect the execution.
70
+ #
64
71
  # The first method call in the Execution creates a Reflection.
65
72
  # Subsequent method calls are shadow executions on cloned objects.
73
+ ##
66
74
  if execution.has_empty_reflections? && !execution.is_reflecting?
67
75
  execution.is_reflecting = true
68
76
 
@@ -103,8 +111,13 @@ module Reflekt
103
111
 
104
112
  end
105
113
 
106
- # Continue execution / shadow execution.
107
- super *args
114
+ # Don't execute skipped methods when reflecting.
115
+ unless execution.is_reflecting? && self.class.reflekt_skipped?(method)
116
+
117
+ # Continue execution / shadow execution.
118
+ super *args
119
+
120
+ end
108
121
 
109
122
  end
110
123
 
@@ -115,6 +128,13 @@ module Reflekt
115
128
 
116
129
  end
117
130
 
131
+ ##
132
+ # Provide Config instance to block.
133
+ ##
134
+ def self.configure
135
+ yield(@@reflekt.config)
136
+ end
137
+
118
138
  private
119
139
 
120
140
  def self.prepended(base)
@@ -132,18 +152,16 @@ module Reflekt
132
152
  def self.reflekt_setup_class()
133
153
 
134
154
  # Receive configuration.
135
- $ENV ||= {}
136
- $ENV[:reflekt] ||= $ENV[:reflekt] = {}
137
- $ENV[:reflekt][:output_directory] = "reflections"
155
+ @@reflekt.config = Config.new()
138
156
 
139
157
  # Set configuration.
140
158
  @@reflekt.path = File.dirname(File.realpath(__FILE__))
141
159
 
142
160
  # Get reflections directory path from config or current execution path.
143
- if $ENV[:reflekt][:output_path]
144
- @@reflekt.output_path = File.join($ENV[:reflekt][:output_path], $ENV[:reflekt][:output_directory])
161
+ if @@reflekt.config.output_path
162
+ @@reflekt.output_path = File.join(@@reflekt.config.output_path, @@reflekt.config.output_directory)
145
163
  else
146
- @@reflekt.output_path = File.join(Dir.pwd, $ENV[:reflekt][:output_directory])
164
+ @@reflekt.output_path = File.join(Dir.pwd, @@reflekt.config.output_directory)
147
165
  end
148
166
 
149
167
  # Create reflections directory.
@@ -161,16 +179,9 @@ module Reflekt
161
179
  @@reflekt.stack = ShadowStack.new()
162
180
 
163
181
  # Create aggregated rule sets.
164
- @@reflekt.aggregator = Aggregator.new()
182
+ @@reflekt.aggregator = Aggregator.new(@@reflekt.config.meta_map)
165
183
  @@reflekt.aggregator.train(db[:controls])
166
184
 
167
- # The amount of reflections to create per method call.
168
- @@reflekt.reflect_amount = 2
169
-
170
- # Limit the amount of reflections that can be created per instance method.
171
- # A method called thousands of times doesn't need that many reflections.
172
- @@reflekt.reflect_limit = 10
173
-
174
185
  # Create renderer.
175
186
  @@reflekt.renderer = Renderer.new(@@reflekt.path, @@reflekt.output_path)
176
187
 
@@ -185,6 +196,10 @@ module Reflekt
185
196
  ##
186
197
  # Skip a method.
187
198
  #
199
+ # @note
200
+ # Class variables cascade to child classes.
201
+ # So a reflekt_skip on the parent class will persist to the child class.
202
+ #
188
203
  # @param method [Symbol] The method name.
189
204
  ##
190
205
  def reflekt_skip(method)
@@ -196,9 +211,9 @@ module Reflekt
196
211
  false
197
212
  end
198
213
 
199
- def reflekt_limit(amount)
200
- @@reflekt.reflect_limit = amount
201
- end
214
+ #def reflekt_limit(amount)
215
+ # @@reflekt.reflect_limit = amount
216
+ #end
202
217
 
203
218
  end
204
219
 
@@ -1,7 +1,13 @@
1
1
  ################################################################################
2
- # All rules behave the same.
2
+ # A pattern that metadata follows.
3
+ #
4
+ # @pattern Abstract class
5
+ #
6
+ # @hierachy
7
+ # 1. Aggregator
8
+ # 2. RuleSet
9
+ # 3. Rule <- YOU ARE HERE
3
10
  #
4
- # @pattern Abstract class.
5
11
  # @see lib/rules for rules.
6
12
  ################################################################################
7
13
 
@@ -1,5 +1,14 @@
1
1
  ################################################################################
2
- # A collection of rules that validate a value.
2
+ # A collection of rules that validate metadata.
3
+ #
4
+ # @patterns
5
+ # - Dependency Injection
6
+ # - Builder
7
+ #
8
+ # @hierachy
9
+ # 1. Aggregator
10
+ # 2. RuleSet <- YOU ARE HERE
11
+ # 3. Rule
3
12
  ################################################################################
4
13
 
5
14
  require 'set'
@@ -8,44 +17,17 @@ class RuleSet
8
17
 
9
18
  attr_accessor :rules
10
19
 
11
- def initialize()
20
+ ##
21
+ # @param meta_map [Hash] The rules to apply to each data type.
22
+ ##
23
+ def initialize(meta_map)
12
24
 
25
+ @meta_map = meta_map
13
26
  @rules = {}
14
27
  @types = Set.new()
15
28
 
16
29
  end
17
30
 
18
- def self.create_sets(args)
19
-
20
- rule_sets = []
21
-
22
- args.each do |arg|
23
- rule_sets << self.create_set(arg)
24
- end
25
-
26
- rule_sets
27
- end
28
-
29
- def self.create_set(value)
30
-
31
- rule_set = RuleSet.new()
32
- value_type = value.class.to_s
33
-
34
- # Creates values for matching data type.
35
- case value_type
36
- when "Integer"
37
- rule = IntegerRule.new()
38
- rule.train(arg)
39
- rule_set.rules[IntegerRule] = rule
40
- when "String"
41
- rule = StringRule.new()
42
- rule.train(arg)
43
- rule_set.rules[StringRule] = rule
44
- end
45
-
46
- rule_set
47
- end
48
-
49
31
  ##
50
32
  # Train rule set on metadata.
51
33
  #
@@ -53,35 +35,29 @@ class RuleSet
53
35
  ##
54
36
  def train(meta)
55
37
 
56
- # Track data type.
57
- @types << meta.class
58
- type = meta.class.to_s
59
-
60
- # Get rule for this data type.
61
- rule = nil
62
- case type
63
- when "Integer"
64
- unless @rules.key? IntegerRule
65
- rule = IntegerRule.new()
66
- @rules[IntegerRule] = rule
67
- else
68
- rule = @rules[IntegerRule]
69
- end
70
- when "String"
71
- unless @rules.key? StringRule
72
- rule = StringRule.new()
73
- @rules[StringRule] = rule
74
- else
75
- rule = @rules[IntegerRule]
38
+ unless meta.nil? || meta[:type].nil?
39
+
40
+ meta_type = meta[:type]
41
+ @types << meta_type
42
+
43
+ # Get rule types for this meta type.
44
+ if @meta_map.key? meta_type
45
+ @meta_map[meta_type].each do |rule_type|
46
+
47
+ # Ensure rule exists.
48
+ if @rules[rule_type].nil?
49
+ @rules << rule_type.new()
50
+ end
51
+
52
+ # Train rule.
53
+ @rules[rule_type].train(meta)
54
+
55
+ end
76
56
  end
77
- end
78
57
 
79
- # Train rule.
80
- unless rule.nil?
81
- rule.train(meta)
82
- end
58
+ return self
83
59
 
84
- return self
60
+ end
85
61
 
86
62
  end
87
63
 
@@ -1,5 +1,7 @@
1
1
  ################################################################################
2
2
  # Track the executions in a shadow call stack.
3
+ #
4
+ # @pattern Stack
3
5
  ################################################################################
4
6
 
5
7
  class ShadowStack
@@ -0,0 +1,33 @@
1
+ require 'Meta'
2
+
3
+ class ArrayMeta < Meta
4
+
5
+ def initialize()
6
+
7
+ @min = nil
8
+ @max = nil
9
+ @length = nil
10
+
11
+ end
12
+
13
+ ##
14
+ # @param value [Array]
15
+ ##
16
+ def load(value)
17
+
18
+ @min = value.min()
19
+ @max = value.max()
20
+ @length = value.length()
21
+
22
+ end
23
+
24
+ def result()
25
+ {
26
+ :type => :array,
27
+ :max => @max,
28
+ :min => @min,
29
+ :length => @length
30
+ }
31
+ end
32
+
33
+ end
@@ -0,0 +1,23 @@
1
+ require 'Meta'
2
+
3
+ class BooleanMeta < Meta
4
+
5
+ def initialize()
6
+ @value = nil
7
+ end
8
+
9
+ ##
10
+ # @param value [Boolean]
11
+ ##
12
+ def load(value)
13
+ @value = value
14
+ end
15
+
16
+ def result()
17
+ {
18
+ :type => :bool,
19
+ :value => @value
20
+ }
21
+ end
22
+
23
+ end
@@ -3,18 +3,14 @@ require 'Meta'
3
3
  class IntegerMeta < Meta
4
4
 
5
5
  def initialize()
6
-
7
6
  @value = nil
8
-
9
7
  end
10
8
 
11
9
  ##
12
10
  # @param value [Integer]
13
11
  ##
14
12
  def load(value)
15
-
16
13
  @value = value
17
-
18
14
  end
19
15
 
20
16
  def result()
@@ -3,18 +3,14 @@ require 'Meta'
3
3
  class StringMeta < Meta
4
4
 
5
5
  def initialize()
6
-
7
6
  @length = nil
8
-
9
7
  end
10
8
 
11
9
  ##
12
- # @param value [Integer]
10
+ # @param value [String]
13
11
  ##
14
12
  def load(value)
15
-
16
13
  @length = value.length
17
-
18
14
  end
19
15
 
20
16
  def result()
@@ -0,0 +1,75 @@
1
+ require 'Rule'
2
+
3
+ class ArrayRule < Rule
4
+
5
+ def initialize()
6
+
7
+ @min = nil
8
+ @max = nil
9
+ @min_length = nil
10
+ @max_length = nil
11
+
12
+ end
13
+
14
+ ##
15
+ # @param meta [ArrayMeta]
16
+ ##
17
+ def train(meta)
18
+
19
+ # Min value.
20
+ if @min.nil?
21
+ @min = meta[:min]
22
+ else
23
+ @min = meta[:min] if meta[:min] < @min
24
+ end
25
+
26
+ # Max value.
27
+ if @max.nil?
28
+ @max = meta[:max]
29
+ else
30
+ @max = meta[:max] if meta[:max] > @max
31
+ end
32
+
33
+ # Min length.
34
+ if @min_length.nil?
35
+ @min_length = meta[:length]
36
+ else
37
+ @min_length = meta[:length] if meta[:length] < @min_length
38
+ end
39
+
40
+ # Max length.
41
+ if @max_length.nil?
42
+ @max_length = meta[:length]
43
+ else
44
+ @max_length = meta[:length] if meta[:length] > @max_length
45
+ end
46
+
47
+ end
48
+
49
+ ##
50
+ # @param value [Array]
51
+ ##
52
+ def test(value)
53
+
54
+ # Min/max value.
55
+ return false if value.min() < @min
56
+ return false if value.max() > @max
57
+
58
+ # Min/max length.
59
+ return false if value.length < @min_length
60
+ return false if value.length > @max_length
61
+
62
+ true
63
+ end
64
+
65
+ def result()
66
+ {
67
+ :type => :array,
68
+ :min => @min,
69
+ :max => @max,
70
+ :min_length => @min_length,
71
+ :max_length => @max_length
72
+ }
73
+ end
74
+
75
+ end
@@ -0,0 +1,42 @@
1
+ require 'set'
2
+ require 'Rule'
3
+
4
+ class BooleanRule < Rule
5
+
6
+ def initialize()
7
+
8
+ @booleans = Set.new()
9
+
10
+ end
11
+
12
+ ##
13
+ # @param meta [BooleanMeta]
14
+ ##
15
+ def train(meta)
16
+
17
+ value = meta[:value]
18
+
19
+ unless value.nil?
20
+ @booleans << value
21
+ end
22
+
23
+ end
24
+
25
+ ##
26
+ # @param value [Boolean]
27
+ ##
28
+ def test(value)
29
+
30
+ @booleans.include? value
31
+
32
+ end
33
+
34
+ def result()
35
+ {
36
+ :type => :bool,
37
+ :is_true => @booleans.include?,
38
+ :is_false => @booleans.include?
39
+ }
40
+ end
41
+
42
+ end
@@ -44,7 +44,8 @@ class IntegerRule < Rule
44
44
  def result()
45
45
  {
46
46
  :type => :int,
47
- :value => @min # Min/max are the same.
47
+ :min => @min,
48
+ :max => @max
48
49
  }
49
50
  end
50
51
 
@@ -13,7 +13,7 @@ class StringRule < Rule
13
13
  end
14
14
 
15
15
  ##
16
- # @param meta [Meta]
16
+ # @param meta [StringMeta]
17
17
  ##
18
18
  def train(meta)
19
19
 
@@ -1,7 +1,7 @@
1
1
  # Reflections
2
2
 
3
- As you use the application reflections will be added to /reflections/db.js.
4
- They can be viewed by opening reflections/index.html, no server setup required.
3
+ As you use your application, reflections will be added to `/reflections/db.js`.
4
+ They can be viewed by opening `/reflections/index.html` in your browser, no server setup required.
5
5
 
6
6
  If you would like to keep or delete reflections then start the server:
7
7
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reflekt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.8
4
+ version: 0.9.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maedi Prichard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-26 00:00:00.000000000 Z
11
+ date: 2020-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rowdb
@@ -32,6 +32,7 @@ extra_rdoc_files: []
32
32
  files:
33
33
  - lib/Accessor.rb
34
34
  - lib/Aggregator.rb
35
+ - lib/Config.rb
35
36
  - lib/Control.rb
36
37
  - lib/Execution.rb
37
38
  - lib/Meta.rb
@@ -42,8 +43,12 @@ files:
42
43
  - lib/Rule.rb
43
44
  - lib/RuleSet.rb
44
45
  - lib/ShadowStack.rb
46
+ - lib/meta/ArrayMeta.rb
47
+ - lib/meta/BooleanMeta.rb
45
48
  - lib/meta/IntegerMeta.rb
46
49
  - lib/meta/StringMeta.rb
50
+ - lib/rules/ArrayRule.rb
51
+ - lib/rules/BooleanRule.rb
47
52
  - lib/rules/IntegerRule.rb
48
53
  - lib/rules/StringRule.rb
49
54
  - lib/web/README.md