vanguard 0.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.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +17 -0
  5. data/Gemfile +7 -0
  6. data/Gemfile.devtools +56 -0
  7. data/Guardfile +18 -0
  8. data/LICENSE +21 -0
  9. data/README.md +80 -0
  10. data/Rakefile +2 -0
  11. data/TODO +3 -0
  12. data/config/flay.yml +3 -0
  13. data/config/flog.yml +2 -0
  14. data/config/mutant.yml +3 -0
  15. data/config/reek.yml +99 -0
  16. data/config/roodi.yml +26 -0
  17. data/config/yardstick.yml +2 -0
  18. data/lib/vanguard.rb +85 -0
  19. data/lib/vanguard/builder.rb +14 -0
  20. data/lib/vanguard/builder/nullary.rb +182 -0
  21. data/lib/vanguard/dsl.rb +43 -0
  22. data/lib/vanguard/dsl/evaluator.rb +197 -0
  23. data/lib/vanguard/evaluator.rb +72 -0
  24. data/lib/vanguard/instance_methods.rb +76 -0
  25. data/lib/vanguard/matcher.rb +19 -0
  26. data/lib/vanguard/matcher/binary.rb +59 -0
  27. data/lib/vanguard/matcher/binary/and.rb +20 -0
  28. data/lib/vanguard/matcher/binary/or.rb +20 -0
  29. data/lib/vanguard/matcher/binary/xor.rb +22 -0
  30. data/lib/vanguard/matcher/nullary.rb +27 -0
  31. data/lib/vanguard/matcher/nullary/equality.rb +46 -0
  32. data/lib/vanguard/matcher/nullary/format.rb +126 -0
  33. data/lib/vanguard/matcher/nullary/greater_than.rb +45 -0
  34. data/lib/vanguard/matcher/nullary/identity.rb +50 -0
  35. data/lib/vanguard/matcher/nullary/inclusion.rb +67 -0
  36. data/lib/vanguard/matcher/nullary/less_than.rb +48 -0
  37. data/lib/vanguard/matcher/nullary/primitive.rb +47 -0
  38. data/lib/vanguard/matcher/nullary/proc.rb +44 -0
  39. data/lib/vanguard/matcher/nullary/value.rb +32 -0
  40. data/lib/vanguard/matcher/unary.rb +45 -0
  41. data/lib/vanguard/matcher/unary/attribute.rb +49 -0
  42. data/lib/vanguard/matcher/unary/not.rb +25 -0
  43. data/lib/vanguard/result.rb +93 -0
  44. data/lib/vanguard/rule.rb +43 -0
  45. data/lib/vanguard/rule/guard.rb +103 -0
  46. data/lib/vanguard/rule/nullary.rb +81 -0
  47. data/lib/vanguard/rule/nullary/attribute.rb +69 -0
  48. data/lib/vanguard/rule/nullary/attribute/absence.rb +19 -0
  49. data/lib/vanguard/rule/nullary/attribute/format.rb +46 -0
  50. data/lib/vanguard/rule/nullary/attribute/inclusion.rb +62 -0
  51. data/lib/vanguard/rule/nullary/attribute/length.rb +184 -0
  52. data/lib/vanguard/rule/nullary/attribute/predicate.rb +10 -0
  53. data/lib/vanguard/rule/nullary/attribute/presence.rb +32 -0
  54. data/lib/vanguard/rule/nullary/attribute/presence/not_blank.rb +0 -0
  55. data/lib/vanguard/rule/nullary/attribute/presence/not_nil.rb +0 -0
  56. data/lib/vanguard/rule/nullary/attribute/primitive.rb +35 -0
  57. data/lib/vanguard/rule/nullary/confirmation.rb +210 -0
  58. data/lib/vanguard/support/blank.rb +29 -0
  59. data/lib/vanguard/validator.rb +116 -0
  60. data/lib/vanguard/validator/builder.rb +52 -0
  61. data/lib/vanguard/violation.rb +84 -0
  62. data/spec/integration/vanguard/dsl/guard_spec.rb +58 -0
  63. data/spec/integration/vanguard/dsl/validates_absence_of_spec.rb +19 -0
  64. data/spec/integration/vanguard/dsl/validates_acceptance_of_spec.rb +19 -0
  65. data/spec/integration/vanguard/dsl/validates_confirmation_of_spec.rb +27 -0
  66. data/spec/integration/vanguard/dsl/validates_format_of_spec.rb +79 -0
  67. data/spec/integration/vanguard/dsl/validates_inclusion_of_spec.rb +23 -0
  68. data/spec/integration/vanguard/dsl/validates_length_of_spec.rb +77 -0
  69. data/spec/integration/vanguard/dsl/validates_presence_of_spec.rb +19 -0
  70. data/spec/integration/vanguard/dsl/validates_value_of_spec.rb +30 -0
  71. data/spec/integration/vanguard/validator_spec.rb +57 -0
  72. data/spec/rcov.opts +6 -0
  73. data/spec/shared/dsl_spec.rb +73 -0
  74. data/spec/spec_helper.rb +3 -0
  75. data/spec/suite.rb +10 -0
  76. data/spec/unit/vanguard/support/blank_spec.rb +72 -0
  77. data/vanguard.gemspec +23 -0
  78. metadata +190 -0
@@ -0,0 +1,50 @@
1
+ module Vanguard
2
+ class Matcher
3
+ class Nullary
4
+ # Equality matcher
5
+ class Identity < self
6
+ include Equalizer.new(:value)
7
+
8
+ # Return value
9
+ #
10
+ # @return [Object]
11
+ #
12
+ # @api private
13
+ #
14
+ attr_reader :value
15
+
16
+ # Test if value for equality
17
+ #
18
+ # @param [Object] value
19
+ #
20
+ # @return [true]
21
+ #
22
+ # @return [false]
23
+ #
24
+ # @api private
25
+ #
26
+ def matches?(value)
27
+ value.equal?(self.value)
28
+ end
29
+
30
+ private
31
+
32
+ # Intialize object
33
+ #
34
+ # @param [Object] value
35
+ #
36
+ # @return [undefined]
37
+ #
38
+ # @api private
39
+ #
40
+ def initialize(value)
41
+ @value = value
42
+ end
43
+
44
+ TRUE = Identity.new(true)
45
+ FALSE = Identity.new(false)
46
+ NIL = Identity.new(nil)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,67 @@
1
+ module Vanguard
2
+ class Matcher
3
+ class Nullary
4
+
5
+ # Matcher that tests for inclusion of value
6
+ class Inclusion < self
7
+ include Equalizer.new(:accepted)
8
+
9
+ # Return accepted values
10
+ #
11
+ # @return [#include?]
12
+ #
13
+ # @api private
14
+ #
15
+ attr_reader :accepted
16
+
17
+ # Test if value is included
18
+ #
19
+ # @param [Object] value
20
+ #
21
+ # @return [true]
22
+ # if value is included
23
+ #
24
+ # @return [false]
25
+ # otherwise
26
+ #
27
+ # @api private
28
+ #
29
+ def matches?(value)
30
+ accepted.include?(value)
31
+ end
32
+
33
+ private
34
+
35
+ # Initialize object
36
+ #
37
+ # @param [#include?] accepted
38
+ #
39
+ # @return [undefined]
40
+ #
41
+ # @api private
42
+ #
43
+ def initialize(accepted)
44
+ @accepted = accepted
45
+ end
46
+
47
+ # Build inclusion matcher
48
+ #
49
+ # @param [Object] value
50
+ #
51
+ # @return [Matcher]
52
+ #
53
+ # @api private
54
+ #
55
+ def self.build(value)
56
+ if value.respond_to?(:include?)
57
+ Inclusion.new(value)
58
+ elsif value.respond_to?(:call)
59
+ Proc.new(value)
60
+ else
61
+ raise "Cannot build inclusion matcher from: #{value.inspect}"
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,48 @@
1
+ module Vanguard
2
+ class Matcher
3
+ class Nullary
4
+
5
+ # Less than matcher
6
+ class LessThan < self
7
+ include Equalizer.new(:value)
8
+
9
+ # Test if value is greater
10
+ #
11
+ # @param [Object] value
12
+ #
13
+ # @return [true]
14
+ #
15
+ # @return [false]
16
+ #
17
+ # @api private
18
+ #
19
+ def matches?(value)
20
+ value < self.value
21
+ end
22
+
23
+ # Return value
24
+ #
25
+ # @return [Object]
26
+ #
27
+ # @api private
28
+ #
29
+ attr_reader :value
30
+
31
+ private
32
+
33
+ # Initialize object
34
+ #
35
+ # @param [Object] value
36
+ #
37
+ # @return [undefined]
38
+ #
39
+ # @api private
40
+ #
41
+ def initialize(value)
42
+ @value = value
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,47 @@
1
+ module Vanguard
2
+ class Matcher
3
+ class Nullary
4
+
5
+ # Matcher that matches primitive types
6
+ class Primitive < self
7
+ include Equalizer.new(:primitive)
8
+
9
+ # Return primitive
10
+ #
11
+ # @return [Class] primitive
12
+ #
13
+ # @api private
14
+ #
15
+ attr_reader :primitive
16
+
17
+ # Test if value is kind of primitive
18
+ #
19
+ # @return [true]
20
+ # if value is kind of primitive
21
+ #
22
+ # @return [false]
23
+ # otherwise
24
+ #
25
+ # @api private
26
+ #
27
+ def matches?(value)
28
+ value.kind_of?(primitive)
29
+ end
30
+
31
+ private
32
+
33
+ # Initialize object
34
+ #
35
+ # @param [Class] primitive
36
+ #
37
+ # @return [undefined]
38
+ #
39
+ # @api private
40
+ #
41
+ def initialize(primitive)
42
+ @primitive = primitive
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,44 @@
1
+ module Vanguard
2
+ class Matcher
3
+ class Nullary
4
+
5
+ # A matcher that delegates to block
6
+ class Proc < self
7
+ include Equalizer.new(:block)
8
+
9
+ # Return block
10
+ #
11
+ # @return [Proc]
12
+ #
13
+ # @api private
14
+ #
15
+ attr_reader :block
16
+
17
+ # Test if value matches
18
+ #
19
+ # @return [true]
20
+ # if block returns non falsy value
21
+ #
22
+ # @return [false]
23
+ # otherwise
24
+ #
25
+ def matches?(input)
26
+ !!@block.call(input)
27
+ end
28
+
29
+ # Initialize object
30
+ #
31
+ # @param [Proc] block
32
+ #
33
+ # @return [undefined]
34
+ #
35
+ # @api private
36
+ #
37
+ def initialize(block)
38
+ @block = block
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ module Vanguard
2
+ class Matcher
3
+ class Nullary
4
+
5
+ # Module for generating value matchers
6
+ #
7
+ # TODO: Move somehere else
8
+ #
9
+ module Value
10
+
11
+ # Build value matcher
12
+ #
13
+ # @param [Object] value
14
+ #
15
+ # @return [Matcher]
16
+ #
17
+ # @api private
18
+ #
19
+ def self.build(value)
20
+ case value
21
+ when Range
22
+ Inclusion.new(value)
23
+ when Fixnum
24
+ Equality.new(value)
25
+ else
26
+ raise "Cannot build value matcher from: #{value.inspect}"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ module Vanguard
2
+ class Matcher
3
+
4
+ # Abstract base class for unary matchers
5
+ class Unary < self
6
+ include AbstractType, Equalizer.new(:operand)
7
+
8
+ # Return operand
9
+ #
10
+ # @return [Matcher]
11
+ #
12
+ # @api private
13
+ #
14
+ attr_reader :operand
15
+
16
+ private
17
+
18
+ # Test if operand matches
19
+ #
20
+ # @param [Object] value
21
+ #
22
+ # @return [true]
23
+ #
24
+ # @return [false]
25
+ #
26
+ # @api private
27
+ #
28
+ def operand_matches?(value)
29
+ operand.matches?(value)
30
+ end
31
+
32
+
33
+ # Initialize object
34
+ #
35
+ # @param [Matcher] operand
36
+ #
37
+ # @api private
38
+ #
39
+ def initialize(operand)
40
+ @operand = operand
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,49 @@
1
+ module Vanguard
2
+ class Matcher
3
+ class Unary
4
+
5
+ # Matcher that matches on attribute of value
6
+ class Attribute < self
7
+
8
+ # Return operand result for length of value
9
+ #
10
+ # @return [true]
11
+ # if operand returns false
12
+ #
13
+ # @return [false]
14
+ # otherwise
15
+ #
16
+ # @api private
17
+ #
18
+ def matches?(value)
19
+ operand_matches?(value.public_send(attribute_name))
20
+ end
21
+
22
+ # Return attribute name
23
+ #
24
+ # @return [Symbol]
25
+ #
26
+ # @api private
27
+ #
28
+ attr_reader :attribute_name
29
+
30
+ private
31
+
32
+ # Initialize object
33
+ #
34
+ # @param [Matcher] operand
35
+ # @param [Symbol] attribute_name
36
+ #
37
+ # @return [undefined]
38
+ #
39
+ # @api private
40
+ #
41
+ def initialize(attribute_name, operand)
42
+ @attribute_name = attribute_name
43
+ super(operand)
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,25 @@
1
+ module Vanguard
2
+ class Matcher
3
+ class Unary
4
+
5
+ # Boolean not matcher
6
+ class NOT < self
7
+
8
+ # Return inverse of operand
9
+ #
10
+ # @return [true]
11
+ # if operand returns false
12
+ #
13
+ # @return [false]
14
+ # otherwise
15
+ #
16
+ # @api private
17
+ #
18
+ def matches?(value)
19
+ !operand_matches?(value)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,93 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Vanguard
4
+
5
+ # Result of a resource validation
6
+ class Result
7
+ include Adamantium::Flat, Enumerable, Equalizer.new(:violations, :validator)
8
+
9
+ # Test if result is valid
10
+ #
11
+ # @return [true]
12
+ # if no rules where violated
13
+ #
14
+ # @return [false]
15
+ # otherwise
16
+ #
17
+ # @api private
18
+ #
19
+ def valid?
20
+ violations.empty?
21
+ end
22
+
23
+ alias_method :success?, :valid?
24
+
25
+ # Return violations for resource
26
+ #
27
+ # @param [Resource] resource
28
+ #
29
+ # @api private
30
+ #
31
+ def violations
32
+ validator.rules.each_with_object(Set.new) do |rule, violations|
33
+ violations.merge(rule.violations(resource))
34
+ end
35
+ end
36
+ memoize :violations
37
+
38
+ # The validation output
39
+ #
40
+ # @return [Object, Set<Violation>]
41
+ # the valid resource, or a set of violations
42
+ #
43
+ # @api private
44
+ #
45
+ def output
46
+ valid? ? resource : violations
47
+ end
48
+
49
+ # Return violations on attribute name
50
+ #
51
+ # @param [Symbol] attribute_name
52
+ #
53
+ # @return [Enumerable<Violation>]
54
+ #
55
+ # @api private
56
+ #
57
+ def on(attribute_name)
58
+ violations.select { |violation| violation.attribute_name == attribute_name }
59
+ end
60
+
61
+ # Return resource
62
+ #
63
+ # @return [Resource]
64
+ #
65
+ # @api private
66
+ #
67
+ attr_reader :resource
68
+
69
+ # Return validator
70
+ #
71
+ # @return [Validator]
72
+ #
73
+ # @api private
74
+ #
75
+ attr_reader :validator
76
+
77
+ private
78
+
79
+ # Initialize object
80
+ #
81
+ # @param [Validator] validator
82
+ # @param [Resource] resource
83
+ #
84
+ # @return [undefined]
85
+ #
86
+ # @api private
87
+ #
88
+ def initialize(validator, resource)
89
+ @validator, @resource = validator, resource
90
+ end
91
+
92
+ end # class ViolationSet
93
+ end # module Vanguard