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.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.travis.yml +17 -0
- data/Gemfile +7 -0
- data/Gemfile.devtools +56 -0
- data/Guardfile +18 -0
- data/LICENSE +21 -0
- data/README.md +80 -0
- data/Rakefile +2 -0
- data/TODO +3 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/mutant.yml +3 -0
- data/config/reek.yml +99 -0
- data/config/roodi.yml +26 -0
- data/config/yardstick.yml +2 -0
- data/lib/vanguard.rb +85 -0
- data/lib/vanguard/builder.rb +14 -0
- data/lib/vanguard/builder/nullary.rb +182 -0
- data/lib/vanguard/dsl.rb +43 -0
- data/lib/vanguard/dsl/evaluator.rb +197 -0
- data/lib/vanguard/evaluator.rb +72 -0
- data/lib/vanguard/instance_methods.rb +76 -0
- data/lib/vanguard/matcher.rb +19 -0
- data/lib/vanguard/matcher/binary.rb +59 -0
- data/lib/vanguard/matcher/binary/and.rb +20 -0
- data/lib/vanguard/matcher/binary/or.rb +20 -0
- data/lib/vanguard/matcher/binary/xor.rb +22 -0
- data/lib/vanguard/matcher/nullary.rb +27 -0
- data/lib/vanguard/matcher/nullary/equality.rb +46 -0
- data/lib/vanguard/matcher/nullary/format.rb +126 -0
- data/lib/vanguard/matcher/nullary/greater_than.rb +45 -0
- data/lib/vanguard/matcher/nullary/identity.rb +50 -0
- data/lib/vanguard/matcher/nullary/inclusion.rb +67 -0
- data/lib/vanguard/matcher/nullary/less_than.rb +48 -0
- data/lib/vanguard/matcher/nullary/primitive.rb +47 -0
- data/lib/vanguard/matcher/nullary/proc.rb +44 -0
- data/lib/vanguard/matcher/nullary/value.rb +32 -0
- data/lib/vanguard/matcher/unary.rb +45 -0
- data/lib/vanguard/matcher/unary/attribute.rb +49 -0
- data/lib/vanguard/matcher/unary/not.rb +25 -0
- data/lib/vanguard/result.rb +93 -0
- data/lib/vanguard/rule.rb +43 -0
- data/lib/vanguard/rule/guard.rb +103 -0
- data/lib/vanguard/rule/nullary.rb +81 -0
- data/lib/vanguard/rule/nullary/attribute.rb +69 -0
- data/lib/vanguard/rule/nullary/attribute/absence.rb +19 -0
- data/lib/vanguard/rule/nullary/attribute/format.rb +46 -0
- data/lib/vanguard/rule/nullary/attribute/inclusion.rb +62 -0
- data/lib/vanguard/rule/nullary/attribute/length.rb +184 -0
- data/lib/vanguard/rule/nullary/attribute/predicate.rb +10 -0
- data/lib/vanguard/rule/nullary/attribute/presence.rb +32 -0
- data/lib/vanguard/rule/nullary/attribute/presence/not_blank.rb +0 -0
- data/lib/vanguard/rule/nullary/attribute/presence/not_nil.rb +0 -0
- data/lib/vanguard/rule/nullary/attribute/primitive.rb +35 -0
- data/lib/vanguard/rule/nullary/confirmation.rb +210 -0
- data/lib/vanguard/support/blank.rb +29 -0
- data/lib/vanguard/validator.rb +116 -0
- data/lib/vanguard/validator/builder.rb +52 -0
- data/lib/vanguard/violation.rb +84 -0
- data/spec/integration/vanguard/dsl/guard_spec.rb +58 -0
- data/spec/integration/vanguard/dsl/validates_absence_of_spec.rb +19 -0
- data/spec/integration/vanguard/dsl/validates_acceptance_of_spec.rb +19 -0
- data/spec/integration/vanguard/dsl/validates_confirmation_of_spec.rb +27 -0
- data/spec/integration/vanguard/dsl/validates_format_of_spec.rb +79 -0
- data/spec/integration/vanguard/dsl/validates_inclusion_of_spec.rb +23 -0
- data/spec/integration/vanguard/dsl/validates_length_of_spec.rb +77 -0
- data/spec/integration/vanguard/dsl/validates_presence_of_spec.rb +19 -0
- data/spec/integration/vanguard/dsl/validates_value_of_spec.rb +30 -0
- data/spec/integration/vanguard/validator_spec.rb +57 -0
- data/spec/rcov.opts +6 -0
- data/spec/shared/dsl_spec.rb +73 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/suite.rb +10 -0
- data/spec/unit/vanguard/support/blank_spec.rb +72 -0
- data/vanguard.gemspec +23 -0
- metadata +190 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Vanguard
|
4
|
+
|
5
|
+
# Abstract base class for resource rules
|
6
|
+
class Rule
|
7
|
+
include AbstractType, Adamantium::Flat
|
8
|
+
|
9
|
+
# Return violations for resource
|
10
|
+
#
|
11
|
+
# @param [Resource] resource
|
12
|
+
#
|
13
|
+
# @return [Enumerable<Violations>]
|
14
|
+
#
|
15
|
+
def violations(resource)
|
16
|
+
evaluate(resource).violations
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return evaluator for resource
|
20
|
+
#
|
21
|
+
# @param [Object] resource
|
22
|
+
# the target object to be validated
|
23
|
+
#
|
24
|
+
# @return [Evaluator]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
#
|
28
|
+
def evaluate(resource)
|
29
|
+
evaluator.new(self, resource)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return evaluator
|
33
|
+
#
|
34
|
+
# @return [Class:Evaluator]
|
35
|
+
#
|
36
|
+
# @api private
|
37
|
+
#
|
38
|
+
def evaluator
|
39
|
+
self.class::Evaluator
|
40
|
+
end
|
41
|
+
|
42
|
+
end # class Rule
|
43
|
+
end # module Vanguard
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Vanguard
|
2
|
+
class Rule
|
3
|
+
class Guard < self
|
4
|
+
# Return matcher
|
5
|
+
#
|
6
|
+
# @return [Matcher]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
#
|
10
|
+
attr_reader :matcher
|
11
|
+
|
12
|
+
# Return operand
|
13
|
+
#
|
14
|
+
# @return [Rule]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
#
|
18
|
+
attr_reader :operand
|
19
|
+
|
20
|
+
# Return attribute name
|
21
|
+
#
|
22
|
+
# @return [Symbol]
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
#
|
26
|
+
def attribute_name
|
27
|
+
operand.attribute_name
|
28
|
+
end
|
29
|
+
memoize :attribute_name
|
30
|
+
|
31
|
+
# Return symbolic type
|
32
|
+
#
|
33
|
+
# @return [Symbol]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
#
|
37
|
+
def type
|
38
|
+
operand.type
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Intialize object
|
44
|
+
#
|
45
|
+
# @param [Matcher] matcher
|
46
|
+
#
|
47
|
+
# @param [Rule] operand
|
48
|
+
#
|
49
|
+
# @return [undefined]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
#
|
53
|
+
def initialize(matcher, operand)
|
54
|
+
@matcher, @operand = matcher, operand
|
55
|
+
end
|
56
|
+
|
57
|
+
class Evaluator < Vanguard::Evaluator
|
58
|
+
# Test if resource is valid
|
59
|
+
#
|
60
|
+
# @return [true]
|
61
|
+
# when guard matches and operand also
|
62
|
+
#
|
63
|
+
# @return [false]
|
64
|
+
# otherwise
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
#
|
68
|
+
def valid?
|
69
|
+
resource = self.resource
|
70
|
+
|
71
|
+
unless matcher.matches?(resource)
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
|
75
|
+
operand.evaluate(resource).valid?
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Return matcher
|
81
|
+
#
|
82
|
+
# @return [Matcher]
|
83
|
+
#
|
84
|
+
# @api private
|
85
|
+
#
|
86
|
+
def matcher
|
87
|
+
rule.matcher
|
88
|
+
end
|
89
|
+
|
90
|
+
# Return operand
|
91
|
+
#
|
92
|
+
# @return [Rule]
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
#
|
96
|
+
def operand
|
97
|
+
rule.operand
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Vanguard
|
2
|
+
class Rule
|
3
|
+
|
4
|
+
# Abstract base class for nullary resource rules
|
5
|
+
class Nullary < self
|
6
|
+
|
7
|
+
# Register dsl method
|
8
|
+
#
|
9
|
+
# @param [Symbol] name
|
10
|
+
#
|
11
|
+
# @return [self]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
#
|
15
|
+
def self.register(name)
|
16
|
+
DSL.register(name, Proxy.new(builder, self))
|
17
|
+
self
|
18
|
+
end
|
19
|
+
private_class_method :register
|
20
|
+
|
21
|
+
# Return builder for nullary rule
|
22
|
+
#
|
23
|
+
# @return [Class:Builder]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
def self.builder
|
28
|
+
self::Builder
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return symbolic type of rule
|
32
|
+
#
|
33
|
+
# @return [Symbol]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
#
|
37
|
+
def type
|
38
|
+
self.class::TYPE
|
39
|
+
end
|
40
|
+
|
41
|
+
# Proxy class to simplify builder registration
|
42
|
+
class Proxy
|
43
|
+
include Adamantium::Flat
|
44
|
+
|
45
|
+
# Run builder with arguments
|
46
|
+
#
|
47
|
+
# @param [Enumerable<Object>] arguments
|
48
|
+
#
|
49
|
+
# @return [Enumerable<Rule>]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
#
|
53
|
+
def run(*arguments)
|
54
|
+
@builder.run(@klass, *arguments)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# Initialize object
|
60
|
+
#
|
61
|
+
# @param [Class:Builder] builder
|
62
|
+
# @param [Class:Rule] klass
|
63
|
+
#
|
64
|
+
# @return [undefined]
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
def initialize(builder, klass)
|
68
|
+
@builder, @klass = builder, klass
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Base class for nullary builders
|
73
|
+
#
|
74
|
+
# TODO: Remove this
|
75
|
+
#
|
76
|
+
class Builder < Builder::Nullary
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Vanguard
|
2
|
+
class Rule
|
3
|
+
# Abstract base class for nullary rules
|
4
|
+
class Nullary
|
5
|
+
|
6
|
+
class Attribute < self
|
7
|
+
include Equalizer.new(:attribute_name, :matcher)
|
8
|
+
|
9
|
+
# Return attribute name
|
10
|
+
#
|
11
|
+
# @return [Symbol]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
#
|
15
|
+
attr_reader :attribute_name
|
16
|
+
|
17
|
+
# Return matcher
|
18
|
+
#
|
19
|
+
# @return [Matcher]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
#
|
23
|
+
attr_reader :matcher
|
24
|
+
|
25
|
+
# Initialize object
|
26
|
+
#
|
27
|
+
# @param [Symbol] attribute_name
|
28
|
+
# the name of the attribute to validate.
|
29
|
+
#
|
30
|
+
# @return [undefined]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
#
|
34
|
+
def initialize(attribute_name, matcher)
|
35
|
+
@attribute_name, @matcher = attribute_name, matcher
|
36
|
+
end
|
37
|
+
|
38
|
+
# Default evaluator
|
39
|
+
class Evaluator < Vanguard::Evaluator
|
40
|
+
# Test if value is valid
|
41
|
+
#
|
42
|
+
# @return [true]
|
43
|
+
# if value is matched by matcher
|
44
|
+
#
|
45
|
+
# @return [false]
|
46
|
+
# otherwise
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
#
|
50
|
+
def valid?
|
51
|
+
matcher.matches?(value)
|
52
|
+
end
|
53
|
+
memoize :valid?
|
54
|
+
|
55
|
+
# Return matcher
|
56
|
+
#
|
57
|
+
# @return [Matcher]
|
58
|
+
#
|
59
|
+
# @api private
|
60
|
+
#
|
61
|
+
def matcher
|
62
|
+
rule.matcher
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
module Vanguard
|
4
|
+
class Rule
|
5
|
+
class Nullary
|
6
|
+
class Attribute
|
7
|
+
|
8
|
+
# Attribute absence rule
|
9
|
+
class Absence < self
|
10
|
+
|
11
|
+
register :validates_absence_of
|
12
|
+
MATCHER = Matcher::Nullary::BLANK
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
module Vanguard
|
4
|
+
class Rule
|
5
|
+
class Nullary
|
6
|
+
class Attribute
|
7
|
+
|
8
|
+
# Rule that tests inputs against formats
|
9
|
+
class Format < self
|
10
|
+
TYPE = :invalid
|
11
|
+
|
12
|
+
# Builder for format rule
|
13
|
+
class Builder < Builder::Nullary
|
14
|
+
REQUIRED_OPTIONS = [:format].freeze
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Return rule for attribute name
|
19
|
+
#
|
20
|
+
# @return [Rule]
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
#
|
24
|
+
def rule(name)
|
25
|
+
klass.new(name, matcher)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return format matcher
|
29
|
+
#
|
30
|
+
# @return [Matcher::Format]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
#
|
34
|
+
def matcher
|
35
|
+
Matcher::Nullary::Format.build(options.fetch(:format))
|
36
|
+
end
|
37
|
+
memoize :matcher
|
38
|
+
end
|
39
|
+
|
40
|
+
register :validates_format_of
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
module Vanguard
|
4
|
+
class Rule
|
5
|
+
class Nullary
|
6
|
+
class Attribute
|
7
|
+
|
8
|
+
# Rule that tests for inclusion
|
9
|
+
class Inclusion < self
|
10
|
+
TYPE = :inclusion
|
11
|
+
|
12
|
+
# Builder for inclusion rule
|
13
|
+
class Builder < Nullary::Builder
|
14
|
+
REQUIRED_OPTIONS = [:within]
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Return matcher
|
19
|
+
#
|
20
|
+
# @return [Matcher]
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
#
|
24
|
+
def matcher
|
25
|
+
Matcher::Nullary::Inclusion.build(options.fetch(:within))
|
26
|
+
end
|
27
|
+
memoize :matcher
|
28
|
+
end
|
29
|
+
|
30
|
+
register :validates_inclusion_of
|
31
|
+
|
32
|
+
|
33
|
+
# Rule that tests for acceptance
|
34
|
+
class Acceptance < self
|
35
|
+
TYPE = :acceptance
|
36
|
+
DEFAULT_ACCEPTED_VALUES = [ '1', 1, 'true', true, 't' ].to_set.deep_freeze
|
37
|
+
|
38
|
+
# Builder for acceptance rule
|
39
|
+
class Builder < Nullary::Builder
|
40
|
+
OPTIONS = [:accept]
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Return matcher
|
45
|
+
#
|
46
|
+
# @return [Matcher]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
#
|
50
|
+
def matcher
|
51
|
+
Matcher::Nullary::Inclusion.new(options.fetch(:acccept) { DEFAULT_ACCEPTED_VALUES })
|
52
|
+
end
|
53
|
+
memoize :matcher
|
54
|
+
end
|
55
|
+
|
56
|
+
register :validates_acceptance_of
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
module Vanguard
|
4
|
+
class Rule
|
5
|
+
class Nullary
|
6
|
+
class Attribute
|
7
|
+
|
8
|
+
# Rule that for length of attribute
|
9
|
+
class Length < self
|
10
|
+
TYPE = :length
|
11
|
+
|
12
|
+
# Builder for length rule
|
13
|
+
class Builder < Nullary::Builder
|
14
|
+
OPTIONS = [:length, :minimum, :maximum]
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Return matcher
|
19
|
+
#
|
20
|
+
# @return [Matcher]
|
21
|
+
#
|
22
|
+
# @api private
|
23
|
+
#
|
24
|
+
def matcher
|
25
|
+
assert_not_empty
|
26
|
+
assert_no_conflict
|
27
|
+
|
28
|
+
length || minmax || minimum || maximum
|
29
|
+
end
|
30
|
+
memoize :matcher
|
31
|
+
|
32
|
+
# Return minmax matcher
|
33
|
+
#
|
34
|
+
# @return [Matcher]
|
35
|
+
# if :minimum and :maximum are present
|
36
|
+
#
|
37
|
+
# @return [nil]
|
38
|
+
# otherwise
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
#
|
42
|
+
def minmax
|
43
|
+
min, max = minimum, maximum
|
44
|
+
|
45
|
+
if min and max
|
46
|
+
return Matcher::Binary::AND.new(min, max)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
memoize :minmax
|
50
|
+
|
51
|
+
# Assert options are not in conflict
|
52
|
+
#
|
53
|
+
# @return [undefined]
|
54
|
+
#
|
55
|
+
# @raise
|
56
|
+
# if options are in conflict
|
57
|
+
#
|
58
|
+
# @api private
|
59
|
+
#
|
60
|
+
def assert_no_conflict
|
61
|
+
if length and (minimum or maximum)
|
62
|
+
raise ":length option is XOR to (:minimum or :maximum)"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Assert options are not empty
|
67
|
+
#
|
68
|
+
# @return [undefined]
|
69
|
+
#
|
70
|
+
# @raise
|
71
|
+
# if non option is given
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
#
|
75
|
+
def assert_not_empty
|
76
|
+
if options.empty?
|
77
|
+
raise ":length, :maxmimum or :minimum must be given as option"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Return minium matcher
|
82
|
+
#
|
83
|
+
# @return [Matcher]
|
84
|
+
# if :minimum option is specified
|
85
|
+
#
|
86
|
+
# @return [nil]
|
87
|
+
# otherwise
|
88
|
+
#
|
89
|
+
# @api private
|
90
|
+
#
|
91
|
+
def minimum
|
92
|
+
process(:minimum, Matcher::Nullary::GreaterThan)
|
93
|
+
end
|
94
|
+
memoize :minimum
|
95
|
+
|
96
|
+
# Return maxmimum matcher
|
97
|
+
#
|
98
|
+
# @return [Matcher]
|
99
|
+
# if :maximum option is specified
|
100
|
+
#
|
101
|
+
# @return [nil]
|
102
|
+
# otherwise
|
103
|
+
#
|
104
|
+
# @api private
|
105
|
+
#
|
106
|
+
def maximum
|
107
|
+
process(:maximum, Matcher::Nullary::LessThan)
|
108
|
+
end
|
109
|
+
memoize :maximum
|
110
|
+
|
111
|
+
# Return matcher
|
112
|
+
#
|
113
|
+
# @param [Symbol] key
|
114
|
+
# @param [Class] klass
|
115
|
+
#
|
116
|
+
# @return [Matcher]
|
117
|
+
# if key option is present
|
118
|
+
#
|
119
|
+
# @return [nil]
|
120
|
+
# otherwise
|
121
|
+
#
|
122
|
+
# @api private
|
123
|
+
#
|
124
|
+
def process(key, klass)
|
125
|
+
option = options.fetch(key) { return }
|
126
|
+
Matcher::Binary::OR.new(
|
127
|
+
klass.new(option),
|
128
|
+
Matcher::Nullary::Equality.new(option)
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Return length matcher
|
133
|
+
#
|
134
|
+
# @return [Matcher]
|
135
|
+
# if :length option is specified
|
136
|
+
#
|
137
|
+
# @return [nil]
|
138
|
+
# otherwise
|
139
|
+
#
|
140
|
+
# @api private
|
141
|
+
#
|
142
|
+
def length
|
143
|
+
option = options.fetch(:length) { return }
|
144
|
+
Matcher::Nullary::Value.build(option)
|
145
|
+
end
|
146
|
+
memoize :length
|
147
|
+
end
|
148
|
+
register :validates_length_of
|
149
|
+
|
150
|
+
# Evaluator for length rules
|
151
|
+
class Evaluator < Attribute::Evaluator
|
152
|
+
|
153
|
+
# Test if value is valid
|
154
|
+
#
|
155
|
+
# @return [true]
|
156
|
+
# if value is valid
|
157
|
+
#
|
158
|
+
# @return [false]
|
159
|
+
# otherwise
|
160
|
+
#
|
161
|
+
# @api private
|
162
|
+
#
|
163
|
+
def valid?
|
164
|
+
matcher.matches?(length)
|
165
|
+
end
|
166
|
+
memoize :valid?
|
167
|
+
|
168
|
+
# Return length
|
169
|
+
#
|
170
|
+
# @return [Fixnum]
|
171
|
+
#
|
172
|
+
# @api private
|
173
|
+
#
|
174
|
+
def length
|
175
|
+
value.length
|
176
|
+
end
|
177
|
+
memoize :length
|
178
|
+
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|