vanguard 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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