whyvalidationssuckin96 1.5.5 → 1.6.0
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.
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.0
|
@@ -1,44 +1,79 @@
|
|
1
1
|
module WhyValidationsSuckIn96
|
2
|
-
# A mixin to help handle the most common case of validating a single attribute on an object. This module has a
|
2
|
+
# A mixin to help handle the most common case of validating a single attribute on an object. This module has a
|
3
3
|
# dependency on SkippableValidation that will most likely be removed in future releases, but is something to be
|
4
4
|
# aware of currently.
|
5
5
|
module AttributeBasedValidation
|
6
|
-
|
6
|
+
|
7
7
|
# An initializer for a validation that checks to see if the required options have been passed for
|
8
8
|
# attribute based validation to work as expected.
|
9
9
|
# @param [Object] validatable An object to be validated
|
10
10
|
# @param [Hash] options The options to set up the validation with
|
11
11
|
# @option options [Symbol] :attribute The attribute on the validatable object to validate against
|
12
|
+
# @option options [true, false] :array Specifies the attribute is an array of values to validate individually
|
12
13
|
# @option options [true, false] :allow_nil If true, skips validation of the value of the attribute is #nil?
|
13
14
|
# @option options [true, false] :allow_blank If true, skips validation of the value of the attribute is #blank?
|
15
|
+
# @option options [true, false] :allow_empty If true, along with :array, skips validation if the array is empty
|
14
16
|
def initialize(validatable, options = {})
|
15
17
|
raise(ArgumentError, "The attribute to validate must be specified as :attribute") unless options[:attribute]
|
18
|
+
@pos = 0 if options[:array]
|
16
19
|
super
|
17
20
|
end
|
18
|
-
|
21
|
+
|
19
22
|
# The attribute to validate against
|
20
23
|
def attribute
|
21
24
|
options[:attribute]
|
22
25
|
end
|
23
|
-
|
26
|
+
|
24
27
|
# The value of the attribute to validate against
|
25
28
|
def attribute_value
|
26
|
-
|
29
|
+
if options[:array]
|
30
|
+
validatable.send(options[:attribute])[@pos]
|
31
|
+
else
|
32
|
+
validatable.send(options[:attribute])
|
33
|
+
end
|
27
34
|
end
|
28
|
-
|
35
|
+
|
29
36
|
# A default validate implementation that skips on #nil?/#blank? attribute values if :allow_nil or :allow_blank
|
30
37
|
# have been set.
|
31
38
|
def validate
|
32
|
-
skip if skip_on_blank? || skip_on_nil?
|
39
|
+
skip if skip_on_empty? || skip_on_blank? || skip_on_nil?
|
33
40
|
super
|
34
41
|
end
|
35
|
-
|
42
|
+
|
43
|
+
# Performs the validation, returning true or false if the validation passes or fails,
|
44
|
+
# or nil if the validation will not run.
|
45
|
+
# @return [true, false, nil]
|
46
|
+
def validates?
|
47
|
+
if options[:array]
|
48
|
+
return @passed = nil if skip_on_empty?
|
49
|
+
reset
|
50
|
+
@pos = 0
|
51
|
+
statuses = []
|
52
|
+
while validating?
|
53
|
+
status = super
|
54
|
+
@pos += 1
|
55
|
+
statuses << status
|
56
|
+
end
|
57
|
+
@passed = statuses.all?
|
58
|
+
else
|
59
|
+
super
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
36
63
|
private
|
37
64
|
|
65
|
+
def validating?
|
66
|
+
(@pos + 1) <= Array(validatable.send(options[:attribute])).size
|
67
|
+
end
|
68
|
+
|
69
|
+
def skip_on_empty?
|
70
|
+
options[:array] && options[:allow_empty] && Array(validatable.send(options[:attribute])).empty?
|
71
|
+
end
|
72
|
+
|
38
73
|
def skip_on_nil?
|
39
74
|
options[:allow_nil] && attribute_value.nil?
|
40
75
|
end
|
41
|
-
|
76
|
+
|
42
77
|
def skip_on_blank?
|
43
78
|
options[:allow_blank] && attribute_value.blank?
|
44
79
|
end
|
@@ -1,41 +1,41 @@
|
|
1
1
|
module WhyValidationsSuckIn96
|
2
|
-
|
2
|
+
|
3
3
|
# Base class to use when implementing validations.
|
4
4
|
class Validation
|
5
|
-
|
5
|
+
|
6
6
|
# A hash of default options for the validation to use.
|
7
7
|
DefaultOptions = {}
|
8
|
-
|
8
|
+
|
9
9
|
# The options the validation was initialized with
|
10
10
|
attr_accessor :options
|
11
|
-
|
11
|
+
|
12
12
|
# The object the validation is validating
|
13
13
|
attr_reader :validatable
|
14
|
-
|
14
|
+
|
15
15
|
class << self
|
16
16
|
attr_accessor :name
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
# @param [Object] validatable An object to be validated
|
20
20
|
# @param [Hash] options The options to set up the validation with
|
21
21
|
def initialize(validatable, options = {})
|
22
22
|
@validatable = validatable
|
23
23
|
@options = self.class::DefaultOptions.merge(options)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Creates a new subclass of this class, used when defining custom validations with a block
|
27
27
|
def self.new_subclass(name, def_block)
|
28
28
|
Class.new(self) do
|
29
29
|
self.name = name.to_sym
|
30
30
|
define_method(:validate, &def_block)
|
31
31
|
private :validate
|
32
|
-
|
32
|
+
|
33
33
|
def inspect
|
34
34
|
"#<WhyValidationsSuckIn96::Validation subclass for validating '#{self.class.name}'> #{super}"
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# Has this validation passed?
|
40
40
|
# @return [true, false]
|
41
41
|
def passed?
|
@@ -47,13 +47,13 @@ module WhyValidationsSuckIn96
|
|
47
47
|
def failed?
|
48
48
|
@passed == false
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
# Has this validation run?
|
52
52
|
# @return [true, false]
|
53
53
|
def has_run?
|
54
54
|
@passed != nil
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
# Performs the validation, returning true or false if the validation passes or fails,
|
58
58
|
# or nil if the validation will not run.
|
59
59
|
# @return [true, false, nil]
|
@@ -64,25 +64,25 @@ module WhyValidationsSuckIn96
|
|
64
64
|
pass
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
# The failure message for this validation.
|
69
69
|
def message
|
70
70
|
@options[:message] || "failed validation"
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
private
|
74
|
-
|
74
|
+
|
75
75
|
def reset
|
76
76
|
@passed = nil
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
def pass
|
80
80
|
throw :validation_done, true
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
def fail
|
84
84
|
throw :validation_done, false
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
end # Validation
|
88
88
|
end # WhyValidationsSuckIn96
|
@@ -3,56 +3,102 @@ require 'whyvalidationssuckin96/attribute_based_validation'
|
|
3
3
|
|
4
4
|
context "attribute based validation mixin" do
|
5
5
|
context "when mixed into a class" do
|
6
|
-
|
6
|
+
|
7
7
|
setup do
|
8
8
|
Class.new(WhyValidationsSuckIn96::Validation) do
|
9
9
|
include WhyValidationsSuckIn96::SkippableValidation
|
10
10
|
include WhyValidationsSuckIn96::AttributeBasedValidation
|
11
|
-
|
11
|
+
|
12
12
|
def validate
|
13
13
|
super
|
14
14
|
pass
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
end # Class.new
|
18
18
|
end # setup
|
19
|
-
|
19
|
+
|
20
20
|
should "fail if no attribute is specified during construction" do
|
21
21
|
topic.new(Object.new)
|
22
22
|
end.raises(ArgumentError, "The attribute to validate must be specified as :attribute")
|
23
|
-
|
23
|
+
|
24
24
|
should "add an attribute accessor" do
|
25
25
|
topic.new(Object.new, :attribute => :foo).attribute
|
26
26
|
end.equals(:foo)
|
27
|
-
|
27
|
+
|
28
28
|
context "when using :allow_nil" do
|
29
|
-
|
29
|
+
|
30
30
|
should "skip validation if the validatable object is #nil?" do
|
31
31
|
inst = topic.new(OpenStruct.new(:test => nil), :allow_nil => true, :attribute => :test)
|
32
32
|
inst.validates?
|
33
33
|
inst.has_run?
|
34
34
|
end.equals(false)
|
35
|
-
|
35
|
+
|
36
36
|
should "not skip validation of the validatable object is non-#nil?" do
|
37
37
|
inst = topic.new(OpenStruct.new(:test => Object.new), :allow_nil => true, :attribute => :test)
|
38
38
|
inst.validates?
|
39
39
|
inst.has_run?
|
40
40
|
end
|
41
41
|
end # when using :allow_nil
|
42
|
-
|
42
|
+
|
43
43
|
context "when using :allow_blank" do
|
44
44
|
should "skip validation if the validatable object is #blank?" do
|
45
45
|
inst = topic.new(OpenStruct.new(:test => ""), :allow_blank => true, :attribute => :test)
|
46
46
|
inst.validates?
|
47
47
|
inst.has_run?
|
48
48
|
end.equals(false)
|
49
|
-
|
49
|
+
|
50
50
|
should "not skip validation if the validatable object is non-#blank?" do
|
51
51
|
inst = topic.new(OpenStruct.new(:test => "bzzt"), :allow_blank => true, :attribute => :test)
|
52
52
|
inst.validates?
|
53
53
|
inst.has_run?
|
54
54
|
end
|
55
55
|
end # when using :allow_blank
|
56
|
-
|
56
|
+
|
57
|
+
context "when using :array" do
|
58
|
+
setup do
|
59
|
+
Class.new(WhyValidationsSuckIn96::Validation) do
|
60
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
61
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
62
|
+
|
63
|
+
def validate
|
64
|
+
super
|
65
|
+
attribute_value.even? ? pass : fail
|
66
|
+
end
|
67
|
+
|
68
|
+
end # Class.new
|
69
|
+
end
|
70
|
+
|
71
|
+
should "fail if any item doesnt validate" do
|
72
|
+
inst = topic.new(OpenStruct.new(:test => [2,4,1,6]), :attribute => :test, :array => true)
|
73
|
+
inst.validates?
|
74
|
+
end.equals(false)
|
75
|
+
|
76
|
+
should "pass if all items validate" do
|
77
|
+
inst = topic.new(OpenStruct.new(:test => [2,4,6]), :attribute => :test, :array => true)
|
78
|
+
inst.validates?
|
79
|
+
end
|
80
|
+
|
81
|
+
should "still pass if the collection state changes between validation calls" do
|
82
|
+
validatable = OpenStruct.new(:test => [1,2,4,6])
|
83
|
+
inst = topic.new(validatable, :allow_empty => true, :attribute => :test, :array => true)
|
84
|
+
first_failed = !inst.validates?
|
85
|
+
validatable.test = [2,4,6]
|
86
|
+
first_failed && inst.validates?
|
87
|
+
end
|
88
|
+
|
89
|
+
context "with :allow_empty" do
|
90
|
+
should "skip validation if the array is empty" do
|
91
|
+
inst = topic.new(OpenStruct.new(:test => []), :allow_empty => true, :attribute => :test, :array => true)
|
92
|
+
inst.validates?
|
93
|
+
inst.has_run?
|
94
|
+
end.equals(false)
|
95
|
+
|
96
|
+
should "not skip validation of the validatable object is non-#empty?" do
|
97
|
+
inst = topic.new(OpenStruct.new(:test => [0]), :allow_empty => true, :attribute => :test, :array => true)
|
98
|
+
inst.validates?
|
99
|
+
inst.has_run?
|
100
|
+
end
|
101
|
+
end # with :allow_empty
|
102
|
+
end # when using :array
|
57
103
|
end # when mixed into a class
|
58
104
|
end # skippable validation mixin
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{whyvalidationssuckin96}
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.6.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["gabrielg", "douglasmeyer"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-09}
|
13
13
|
s.description = %q{A library for setting up model validations, such as in ActiveRecord.}
|
14
14
|
s.email = %q{gabriel.gironda@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: whyvalidationssuckin96
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- gabrielg
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2010-03-
|
13
|
+
date: 2010-03-09 00:00:00 -06:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|