whyvalidationssuckin96 1.0.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/.document +5 -0
- data/.gitignore +22 -0
- data/LICENSE +20 -0
- data/README.md +121 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/doc/ActiveRecord/RecordInvalid.html +258 -0
- data/doc/ActiveRecord.html +93 -0
- data/doc/FalseClass.html +87 -0
- data/doc/NilClass.html +87 -0
- data/doc/Numeric.html +87 -0
- data/doc/Object.html +79 -0
- data/doc/String.html +87 -0
- data/doc/TrueClass.html +87 -0
- data/doc/WhyValidationsSuckIn96/ActiveRecord/InstanceMethods.html +156 -0
- data/doc/WhyValidationsSuckIn96/ActiveRecord.html +192 -0
- data/doc/WhyValidationsSuckIn96/AttributeBasedValidation.html +464 -0
- data/doc/WhyValidationsSuckIn96/SkippableValidation.html +194 -0
- data/doc/WhyValidationsSuckIn96/ValidatesAcceptance.html +254 -0
- data/doc/WhyValidationsSuckIn96/ValidatesAssociated.html +250 -0
- data/doc/WhyValidationsSuckIn96/ValidatesConfirmation.html +251 -0
- data/doc/WhyValidationsSuckIn96/ValidatesExclusion.html +388 -0
- data/doc/WhyValidationsSuckIn96/ValidatesFormat.html +387 -0
- data/doc/WhyValidationsSuckIn96/ValidatesInclusion.html +388 -0
- data/doc/WhyValidationsSuckIn96/ValidatesLength.html +469 -0
- data/doc/WhyValidationsSuckIn96/ValidatesNumericality.html +267 -0
- data/doc/WhyValidationsSuckIn96/ValidatesPresence.html +244 -0
- data/doc/WhyValidationsSuckIn96/ValidatesUniqueness.html +289 -0
- data/doc/WhyValidationsSuckIn96/Validation.html +934 -0
- data/doc/WhyValidationsSuckIn96/ValidationBuilder.html +391 -0
- data/doc/WhyValidationsSuckIn96/ValidationSupport/ClassMethods.html +249 -0
- data/doc/WhyValidationsSuckIn96/ValidationSupport/InstanceMethods.html +484 -0
- data/doc/WhyValidationsSuckIn96/ValidationSupport.html +168 -0
- data/doc/WhyValidationsSuckIn96.html +97 -0
- data/doc/_index.html +346 -0
- data/doc/class_list.html +293 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +23 -0
- data/doc/css/style.css +263 -0
- data/doc/file.README.html +173 -0
- data/doc/file_list.html +29 -0
- data/doc/index.html +173 -0
- data/doc/js/app.js +91 -0
- data/doc/js/full_list.js +39 -0
- data/doc/js/jquery.js +19 -0
- data/doc/method_list.html +462 -0
- data/doc/top-level-namespace.html +81 -0
- data/lib/whyvalidationssuckin96/attribute_based_validation.rb +46 -0
- data/lib/whyvalidationssuckin96/constants.rb +3 -0
- data/lib/whyvalidationssuckin96/ext/blank.rb +47 -0
- data/lib/whyvalidationssuckin96/macros/validates_acceptance.rb +36 -0
- data/lib/whyvalidationssuckin96/macros/validates_associated.rb +33 -0
- data/lib/whyvalidationssuckin96/macros/validates_confirmation.rb +40 -0
- data/lib/whyvalidationssuckin96/macros/validates_exclusion.rb +38 -0
- data/lib/whyvalidationssuckin96/macros/validates_format.rb +38 -0
- data/lib/whyvalidationssuckin96/macros/validates_inclusion.rb +38 -0
- data/lib/whyvalidationssuckin96/macros/validates_length.rb +98 -0
- data/lib/whyvalidationssuckin96/macros/validates_numericality.rb +56 -0
- data/lib/whyvalidationssuckin96/macros/validates_presence.rb +30 -0
- data/lib/whyvalidationssuckin96/macros.rb +9 -0
- data/lib/whyvalidationssuckin96/rails/active_record.rb +94 -0
- data/lib/whyvalidationssuckin96/rails/macros/validates_uniqueness.rb +87 -0
- data/lib/whyvalidationssuckin96/rails/macros.rb +1 -0
- data/lib/whyvalidationssuckin96/skippable_validation.rb +59 -0
- data/lib/whyvalidationssuckin96/validation.rb +88 -0
- data/lib/whyvalidationssuckin96/validation_builder.rb +56 -0
- data/lib/whyvalidationssuckin96/validation_support.rb +74 -0
- data/lib/whyvalidationssuckin96.rb +4 -0
- data/test/attribute_based_validation_test.rb +58 -0
- data/test/macros/validates_acceptance_test.rb +64 -0
- data/test/macros/validates_associated_test.rb +60 -0
- data/test/macros/validates_confirmation_test.rb +63 -0
- data/test/macros/validates_exclusion_test.rb +37 -0
- data/test/macros/validates_format_test.rb +43 -0
- data/test/macros/validates_inclusion_test.rb +37 -0
- data/test/macros/validates_length_test.rb +179 -0
- data/test/macros/validates_numericality_test.rb +129 -0
- data/test/macros/validates_presence_test.rb +31 -0
- data/test/rails/active_record_test.rb +187 -0
- data/test/rails/active_record_test_helper.rb +90 -0
- data/test/rails/macros/validates_uniqueness_test.rb +153 -0
- data/test/skippable_validation_test.rb +102 -0
- data/test/teststrap.rb +4 -0
- data/test/validation_builder_test.rb +62 -0
- data/test/validation_support_test.rb +209 -0
- data/test/validation_test.rb +101 -0
- data/whyvalidationssuckin96.gemspec +153 -0
- metadata +189 -0
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'teststrap'
|
2
|
+
require 'rails/active_record_test_helper'
|
3
|
+
|
4
|
+
context "active record integration" do
|
5
|
+
|
6
|
+
should "automatically be mixed into the records of the active variety" do
|
7
|
+
ActiveRecord::Base
|
8
|
+
end.respond_to(:validation_collection)
|
9
|
+
|
10
|
+
context "given an example class, 'VisualWork'" do
|
11
|
+
setup { VisualWork }
|
12
|
+
|
13
|
+
should "not save when invalid?" do
|
14
|
+
inst = topic.new
|
15
|
+
inst.save
|
16
|
+
inst.new_record?
|
17
|
+
end
|
18
|
+
|
19
|
+
should "save when valid" do
|
20
|
+
inst = topic.new(:name => "test")
|
21
|
+
inst.save
|
22
|
+
!inst.new_record?
|
23
|
+
end
|
24
|
+
|
25
|
+
should "raise the expected exception when invalid and using save!" do
|
26
|
+
inst = topic.new
|
27
|
+
inst.save!
|
28
|
+
end.raises(ActiveRecord::RecordInvalid)
|
29
|
+
|
30
|
+
should "raise the expected exception when invalid and using create!" do
|
31
|
+
topic.create!
|
32
|
+
end.raises(ActiveRecord::RecordInvalid)
|
33
|
+
|
34
|
+
end # given an example class, 'VisualWork'
|
35
|
+
|
36
|
+
context "given an example class, 'MusicalWork'" do
|
37
|
+
setup { MusicalWork }
|
38
|
+
|
39
|
+
should "have four validations in the collection" do
|
40
|
+
topic.validation_collection.size
|
41
|
+
end.equals(4)
|
42
|
+
|
43
|
+
context "an instance testing basic validation functionality" do
|
44
|
+
setup { topic.new }
|
45
|
+
|
46
|
+
should "have three passes when the 'state' attribute is nil" do
|
47
|
+
topic.state = nil
|
48
|
+
topic.valid?
|
49
|
+
topic.passed_validations.size
|
50
|
+
end.equals(3)
|
51
|
+
|
52
|
+
should "have one fail when the 'state' attribute is :fail" do
|
53
|
+
topic.state = :fail
|
54
|
+
topic.valid?
|
55
|
+
topic.failed_validations.size
|
56
|
+
end.equals(1)
|
57
|
+
|
58
|
+
should "have two passes when the 'state' attribute is :fail" do
|
59
|
+
topic.state = :fail
|
60
|
+
topic.valid?
|
61
|
+
topic.passed_validations.size
|
62
|
+
end.equals(2)
|
63
|
+
|
64
|
+
should "not be allowed to be saved in an invalid state" do
|
65
|
+
topic.state = :fail
|
66
|
+
topic.save
|
67
|
+
end.equals(false)
|
68
|
+
|
69
|
+
should "not respond to the 'errors' method" do
|
70
|
+
topic.respond_to?(:errors)
|
71
|
+
end.equals(false)
|
72
|
+
|
73
|
+
end # an instance testing basic validation functionality
|
74
|
+
|
75
|
+
context "an instance testing validation :on specification" do
|
76
|
+
context "on create" do
|
77
|
+
setup do
|
78
|
+
instance = topic.new
|
79
|
+
instance.save
|
80
|
+
instance.validations_run
|
81
|
+
end
|
82
|
+
|
83
|
+
should "not have run the validation specified for :update" do
|
84
|
+
topic.include?(:validation_that_runs_on_update)
|
85
|
+
end.equals(false)
|
86
|
+
|
87
|
+
should "have run the validation specified for :create" do
|
88
|
+
topic
|
89
|
+
end.includes(:validation_that_runs_on_create)
|
90
|
+
end # on create
|
91
|
+
|
92
|
+
context "on update" do
|
93
|
+
setup do
|
94
|
+
instance = topic.new
|
95
|
+
instance.save
|
96
|
+
raise "Whoa there. Topic needs to be a saved record." if instance.new_record?
|
97
|
+
instance.validations_run.clear
|
98
|
+
instance.save
|
99
|
+
instance.validations_run
|
100
|
+
end
|
101
|
+
|
102
|
+
should "have run the validation specified for :update" do
|
103
|
+
topic
|
104
|
+
end.includes(:validation_that_runs_on_update)
|
105
|
+
|
106
|
+
should "not have run the validation specified for :create" do
|
107
|
+
topic.include?(:validation_that_runs_on_create)
|
108
|
+
end.equals(false)
|
109
|
+
end # on update
|
110
|
+
end # an instance testing validation :on specification
|
111
|
+
|
112
|
+
context "an instance testing callback functionality" do
|
113
|
+
|
114
|
+
context "on create" do
|
115
|
+
setup do
|
116
|
+
instance = topic.new
|
117
|
+
instance.state = :fail
|
118
|
+
instance.save
|
119
|
+
instance.callbacks_run
|
120
|
+
end
|
121
|
+
|
122
|
+
should "have run the before_validation callback" do
|
123
|
+
topic
|
124
|
+
end.includes(:before_validation)
|
125
|
+
|
126
|
+
should "have run the before_validation_on_create callback" do
|
127
|
+
topic
|
128
|
+
end.includes(:before_validation_on_create)
|
129
|
+
|
130
|
+
should "not have run the before_validation_on_update callback" do
|
131
|
+
topic.include?(:before_validation_on_update)
|
132
|
+
end.equals(false)
|
133
|
+
|
134
|
+
should "have run the after_validation callback" do
|
135
|
+
topic
|
136
|
+
end.includes(:after_validation)
|
137
|
+
|
138
|
+
should "have run the after_validation_on_create callback" do
|
139
|
+
topic
|
140
|
+
end.includes(:after_validation_on_create)
|
141
|
+
|
142
|
+
should "not have run the after_validation_on_update callback" do
|
143
|
+
topic.include?(:after_validation_on_update)
|
144
|
+
end.equals(false)
|
145
|
+
|
146
|
+
end # on create
|
147
|
+
|
148
|
+
context "on update" do
|
149
|
+
setup do
|
150
|
+
instance = topic.new
|
151
|
+
instance.state = nil
|
152
|
+
instance.save
|
153
|
+
raise "Whoa there. Topic needs to be a saved record." if instance.new_record?
|
154
|
+
instance.callbacks_run.clear
|
155
|
+
instance.save
|
156
|
+
instance.callbacks_run
|
157
|
+
end
|
158
|
+
|
159
|
+
should "have run the before_validation callback" do
|
160
|
+
topic
|
161
|
+
end.includes(:before_validation)
|
162
|
+
|
163
|
+
should "not have run the before_validation_on_create callback" do
|
164
|
+
topic.include?(:before_validation_on_create)
|
165
|
+
end.equals(false)
|
166
|
+
|
167
|
+
should "not have run the before_validation_on_update callback" do
|
168
|
+
topic
|
169
|
+
end.includes(:before_validation_on_update)
|
170
|
+
|
171
|
+
should "have run the after_validation callback" do
|
172
|
+
topic
|
173
|
+
end.includes(:after_validation)
|
174
|
+
|
175
|
+
should "have run the after_validation_on_create callback" do
|
176
|
+
topic.include?(:after_validation_on_create)
|
177
|
+
end.equals(false)
|
178
|
+
|
179
|
+
should "not have run the after_validation_on_update callback" do
|
180
|
+
topic
|
181
|
+
end.includes(:after_validation_on_update)
|
182
|
+
|
183
|
+
end # on create
|
184
|
+
|
185
|
+
end # an instance testing callback functionality
|
186
|
+
end # given an example class, 'MusicalWork'
|
187
|
+
end # active record integration
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'whyvalidationssuckin96/rails/active_record'
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
4
|
+
ActiveRecord::Schema.define(:version => 1) do
|
5
|
+
create_table :musical_works do |t|
|
6
|
+
t.string :name
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table :visual_works do |t|
|
10
|
+
t.string :name
|
11
|
+
t.string :author
|
12
|
+
t.string :type
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class MusicalWork < ActiveRecord::Base
|
17
|
+
attr_accessor :state, :callbacks_run, :validations_run
|
18
|
+
|
19
|
+
def after_initialize
|
20
|
+
@callbacks_run = []
|
21
|
+
@validations_run = []
|
22
|
+
end
|
23
|
+
|
24
|
+
setup_validations do
|
25
|
+
validate :something_that_passes do
|
26
|
+
pass if validatable.state == :pass
|
27
|
+
end
|
28
|
+
|
29
|
+
validate :something_that_fails do
|
30
|
+
fail if validatable.state == :fail
|
31
|
+
end
|
32
|
+
|
33
|
+
validate :validation_that_runs_on_update, :on => :update do
|
34
|
+
validatable.validations_run << :validation_that_runs_on_update
|
35
|
+
end
|
36
|
+
|
37
|
+
validate :validation_that_runs_on_create, :on => :create do
|
38
|
+
validatable.validations_run << :validation_that_runs_on_create
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def before_validation_on_update
|
43
|
+
callbacks_run << :before_validation_on_update
|
44
|
+
end
|
45
|
+
|
46
|
+
def before_validation
|
47
|
+
callbacks_run << :before_validation
|
48
|
+
end
|
49
|
+
|
50
|
+
def before_validation_on_create
|
51
|
+
callbacks_run << :before_validation_on_create
|
52
|
+
end
|
53
|
+
|
54
|
+
def after_validation_on_update
|
55
|
+
callbacks_run << :after_validation_on_update
|
56
|
+
end
|
57
|
+
|
58
|
+
def after_validation
|
59
|
+
callbacks_run << :after_validation
|
60
|
+
end
|
61
|
+
|
62
|
+
def after_validation_on_create
|
63
|
+
callbacks_run << :after_validation_on_create
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
class VisualWork < ActiveRecord::Base
|
69
|
+
setup_validations do
|
70
|
+
validates_presence_of :name
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Photograph < VisualWork
|
75
|
+
setup_validations do
|
76
|
+
validates_uniqueness_of :author, :base_class_scope => false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class Painting < VisualWork
|
81
|
+
setup_validations do
|
82
|
+
validates_uniqueness_of :author, :base_class_scope => true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class Collage < VisualWork
|
87
|
+
setup_validations do
|
88
|
+
validates_uniqueness_of :name, :scope => :author
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'teststrap'
|
2
|
+
require 'rails/active_record_test_helper'
|
3
|
+
|
4
|
+
context "validates uniqueness" do
|
5
|
+
|
6
|
+
should "add a validation macro" do
|
7
|
+
WhyValidationsSuckIn96::ValidationBuilder.instance_methods
|
8
|
+
end.includes('validates_uniqueness_of')
|
9
|
+
|
10
|
+
context "with some default options" do
|
11
|
+
setup do
|
12
|
+
WhyValidationsSuckIn96::ValidatesUniqueness.new(Object.new, :attribute => :username)
|
13
|
+
end
|
14
|
+
|
15
|
+
should "have a message accessor with a default message" do
|
16
|
+
topic.message
|
17
|
+
end.equals("has already been taken")
|
18
|
+
|
19
|
+
should "default to being case insensitive" do
|
20
|
+
topic.options[:case_sensitive]
|
21
|
+
end.equals(false)
|
22
|
+
|
23
|
+
should "default :base_class_scope to true" do
|
24
|
+
topic.options[:base_class_scope]
|
25
|
+
end.equals(true)
|
26
|
+
end # with some default options
|
27
|
+
|
28
|
+
context "validating an object" do
|
29
|
+
|
30
|
+
context "with default options" do
|
31
|
+
setup do
|
32
|
+
Class.new(VisualWork) do
|
33
|
+
setup_validations do
|
34
|
+
validates_uniqueness_of :name
|
35
|
+
end
|
36
|
+
end # VisualWork
|
37
|
+
end # setup do
|
38
|
+
|
39
|
+
should "mark the second object with the same name as invalid" do
|
40
|
+
work = topic.new(:name => "example")
|
41
|
+
work.save!
|
42
|
+
other_work = topic.new(:name => "example")
|
43
|
+
!other_work.valid? && other_work.failed_validations.detect do |fv|
|
44
|
+
fv.kind_of?(WhyValidationsSuckIn96::ValidatesUniqueness) && fv.attribute == :name
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
should "allow two objects with different names" do
|
49
|
+
work = topic.new(:name => "example one")
|
50
|
+
work.save!
|
51
|
+
other = topic.new(:name => "example two")
|
52
|
+
other.valid?
|
53
|
+
end
|
54
|
+
|
55
|
+
should "not care about case sensitivity by default" do
|
56
|
+
work = topic.new(:name => "cAsE SeNsItiViTy")
|
57
|
+
work.save!
|
58
|
+
other_work = topic.new(:name => "case sensitivity")
|
59
|
+
!other_work.valid? && other_work.failed_validations.detect do |fv|
|
60
|
+
fv.kind_of?(WhyValidationsSuckIn96::ValidatesUniqueness) && fv.attribute == :name
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
should "allow the one object to be saved twice and not violate the constraint" do
|
65
|
+
work = topic.new(:name => "screenshot")
|
66
|
+
work.save
|
67
|
+
work.author = "gabe"
|
68
|
+
work.save
|
69
|
+
end
|
70
|
+
end # with default options
|
71
|
+
|
72
|
+
context "specifying case sensitivity" do
|
73
|
+
setup do
|
74
|
+
Class.new(VisualWork) do
|
75
|
+
setup_validations do
|
76
|
+
validates_uniqueness_of :name, :case_sensitive => true
|
77
|
+
end
|
78
|
+
end # VisualWork
|
79
|
+
end # setup do
|
80
|
+
|
81
|
+
should "allow objects with the same name and different case to be valid" do
|
82
|
+
work = topic.create!(:name => "CASE SENSITIVE IS TRUE")
|
83
|
+
other_work = topic.new(:name => "case sensitive is true")
|
84
|
+
other_work.valid?
|
85
|
+
end
|
86
|
+
|
87
|
+
should "mark the second object with the name in the same case as invalid" do
|
88
|
+
work = topic.create(:name => "SO WHAT")
|
89
|
+
other_work = topic.new(:name => "SO WHAT")
|
90
|
+
!other_work.valid? && other_work.failed_validations.detect do |fv|
|
91
|
+
fv.kind_of?(WhyValidationsSuckIn96::ValidatesUniqueness) && fv.attribute == :name
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end # specifying case sensitivity
|
95
|
+
|
96
|
+
context "specifying base class scope" do
|
97
|
+
context "as false" do
|
98
|
+
should "allow records to be created in different subclasses that violate the uniqueness" do
|
99
|
+
Painting.create!(:name => "painting one", :author => "humbug")
|
100
|
+
Photograph.new(:name => "photo one", :author => "humbug").valid?
|
101
|
+
end
|
102
|
+
|
103
|
+
should "not allow records to be created in the same class that violate the uniqueness" do
|
104
|
+
Photograph.create!(:name => "photo one", :author => "gus")
|
105
|
+
photo = Photograph.new(:name => "photo two", :author => "gus")
|
106
|
+
!photo.valid? && photo.failed_validations.detect do |fv|
|
107
|
+
fv.kind_of?(WhyValidationsSuckIn96::ValidatesUniqueness) && fv.attribute == :author
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end # as false
|
111
|
+
|
112
|
+
context "as true" do
|
113
|
+
should "not allow records to be created that violate a uniqueness constraint based on the base class" do
|
114
|
+
VisualWork.create!(:name => "mspaint", :author => "dan")
|
115
|
+
work = Painting.new(:name => "the treachery of images", :author => "dan")
|
116
|
+
!work.valid? && work.failed_validations.detect do |fv|
|
117
|
+
fv.kind_of?(WhyValidationsSuckIn96::ValidatesUniqueness) && fv.attribute == :author
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
should "allow records to be created that don't violate the uniqueness constraint" do
|
122
|
+
VisualWork.create!(:name => "photoshop", :author => "alex")
|
123
|
+
Painting.create!(:name => "paintshop", :author => "evan")
|
124
|
+
end
|
125
|
+
end # as true
|
126
|
+
end # specifying base class scope
|
127
|
+
|
128
|
+
context "specifying scope options" do
|
129
|
+
should "pass when uniqueness is valid against the given scope column" do
|
130
|
+
Collage.create!(:name => "wired snippets", :author => "dan")
|
131
|
+
work = Collage.new(:name => "wired snippets", :author => "gabe")
|
132
|
+
work.valid?
|
133
|
+
end
|
134
|
+
|
135
|
+
should "fail when uniqueness is invalid against the given scope column" do
|
136
|
+
Collage.create!(:name => "rolling stone snippets", :author => "gabe")
|
137
|
+
work = Collage.new(:name => "rolling stone snippets", :author => "gabe")
|
138
|
+
!work.valid? && work.failed_validations.detect do |fv|
|
139
|
+
fv.kind_of?(WhyValidationsSuckIn96::ValidatesUniqueness) && fv.attribute == :name
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end # specifying scope options
|
143
|
+
|
144
|
+
context "when using with_scope" do
|
145
|
+
should "basically just ignore with_scope" do
|
146
|
+
Painting.create!(:author => "fred", :name => "bbzzzt")
|
147
|
+
Painting.send(:with_scope, :find => {:conditions => {:author => "fred"}}) do
|
148
|
+
Painting.create!(:author => "myles", :name => "bitchesbrew")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end # when using with_scope
|
152
|
+
end # validating an object
|
153
|
+
end # validates uniqueness
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'teststrap'
|
2
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
3
|
+
|
4
|
+
context "skippable validation mixin" do
|
5
|
+
context "when mixed into a class" do
|
6
|
+
|
7
|
+
setup do
|
8
|
+
Class.new(WhyValidationsSuckIn96::Validation) do
|
9
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
10
|
+
attr_accessor :skip_validation
|
11
|
+
|
12
|
+
def validate
|
13
|
+
super
|
14
|
+
options[:should_pass] ? pass : fail
|
15
|
+
end
|
16
|
+
end # Class.new
|
17
|
+
end # setup
|
18
|
+
|
19
|
+
context "when specifying an :if option" do
|
20
|
+
context "as a block" do
|
21
|
+
|
22
|
+
setup do
|
23
|
+
topic.new(Object.new, :if => lambda { !skip_validation })
|
24
|
+
end
|
25
|
+
|
26
|
+
should "not have run if the block returns false" do
|
27
|
+
topic.skip_validation = true
|
28
|
+
topic.validates?
|
29
|
+
topic.has_run?
|
30
|
+
end.equals(false)
|
31
|
+
|
32
|
+
should "have run if the block returns true" do
|
33
|
+
topic.skip_validation = false
|
34
|
+
topic.validates?
|
35
|
+
topic.has_run?
|
36
|
+
end
|
37
|
+
end # as a block
|
38
|
+
|
39
|
+
context "as a symbol" do
|
40
|
+
validatable = nil
|
41
|
+
|
42
|
+
setup do
|
43
|
+
validatable = OpenStruct.new(:allow_validation => true)
|
44
|
+
topic.new(validatable, :if => :allow_validation)
|
45
|
+
end
|
46
|
+
|
47
|
+
should "not have run if the method named by the symbol returns false" do
|
48
|
+
validatable.allow_validation = false
|
49
|
+
topic.validates?
|
50
|
+
topic.has_run?
|
51
|
+
end.equals(false)
|
52
|
+
|
53
|
+
should "have run if the method named by the symbol returns true" do
|
54
|
+
validatable.allow_validation = true
|
55
|
+
topic.validates?
|
56
|
+
topic.has_run?
|
57
|
+
end
|
58
|
+
end # as a symbol
|
59
|
+
end # when specifying an :if option
|
60
|
+
|
61
|
+
context "when specifying an :unless option" do
|
62
|
+
context "as a block" do
|
63
|
+
setup do
|
64
|
+
topic.new(Object.new, :unless => lambda { skip_validation })
|
65
|
+
end
|
66
|
+
|
67
|
+
should "have run if the block returns false" do
|
68
|
+
topic.skip_validation = false
|
69
|
+
topic.validates?
|
70
|
+
topic.has_run?
|
71
|
+
end
|
72
|
+
|
73
|
+
should "not have run if the block returns true" do
|
74
|
+
topic.skip_validation = true
|
75
|
+
topic.validates?
|
76
|
+
topic.has_run?
|
77
|
+
end.equals(false)
|
78
|
+
end # as a block
|
79
|
+
|
80
|
+
context "as a symbol" do
|
81
|
+
validatable = nil
|
82
|
+
|
83
|
+
setup do
|
84
|
+
validatable = OpenStruct.new(:skip_validation => true)
|
85
|
+
topic.new(validatable, :unless => :skip_validation)
|
86
|
+
end
|
87
|
+
|
88
|
+
should "have run if the method named by the symbol returns false" do
|
89
|
+
validatable.skip_validation = false
|
90
|
+
topic.validates?
|
91
|
+
topic.has_run?
|
92
|
+
end
|
93
|
+
|
94
|
+
should "not have run if the method named by the symbol returns true" do
|
95
|
+
validatable.skip_validation = true
|
96
|
+
topic.validates?
|
97
|
+
topic.has_run?
|
98
|
+
end.equals(false)
|
99
|
+
end # as a symbol
|
100
|
+
end # when specifying an :unless option
|
101
|
+
end # when mixed into a class
|
102
|
+
end # skippable validation mixin
|
data/test/teststrap.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'teststrap'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
context "validation builder" do
|
5
|
+
context "when defining some standard validations" do
|
6
|
+
setup do
|
7
|
+
fake_validation_target = OpenStruct.new(:validation_collection => [])
|
8
|
+
validation_block = lambda do
|
9
|
+
validate(:validates_whatever) {}
|
10
|
+
validate(:validates_whenever) {}
|
11
|
+
end
|
12
|
+
WhyValidationsSuckIn96::ValidationBuilder.new(fake_validation_target, validation_block).create_validations!
|
13
|
+
fake_validation_target
|
14
|
+
end
|
15
|
+
|
16
|
+
should "have a validates_whatever validation in the collection" do
|
17
|
+
topic.validation_collection.detect { |(validation, opts)| validation.name == :validates_whatever }
|
18
|
+
end
|
19
|
+
|
20
|
+
should "have a validates_whenever validation in the collection" do
|
21
|
+
topic.validation_collection.detect { |(validation, opts)| validation.name == :validates_whenever }
|
22
|
+
end
|
23
|
+
|
24
|
+
should "have Validation subclasses as the values for the validation_collection" do
|
25
|
+
topic.validation_collection.all? {|(klass,opts)| klass.ancestors.include?(WhyValidationsSuckIn96::Validation)}
|
26
|
+
end
|
27
|
+
end # when defining some standard validations
|
28
|
+
|
29
|
+
context "when defining multiple validations with the same name in the one validation definition" do
|
30
|
+
setup do
|
31
|
+
fake_validation_target = OpenStruct.new(:validation_collection => [])
|
32
|
+
validation_block = lambda do
|
33
|
+
validate(:we_are_clones) {}
|
34
|
+
validate(:we_are_clones) {}
|
35
|
+
end # validation_block
|
36
|
+
WhyValidationsSuckIn96::ValidationBuilder.new(fake_validation_target, validation_block).create_validations!
|
37
|
+
fake_validation_target
|
38
|
+
end
|
39
|
+
|
40
|
+
should "only have one validation in the collection on the target" do
|
41
|
+
topic.validation_collection.size
|
42
|
+
end.equals(1)
|
43
|
+
|
44
|
+
end # when defining multiple validations with the same name in the one validation definition
|
45
|
+
|
46
|
+
context "when defining multiple validations with the same name in more than one validation definition" do
|
47
|
+
setup do
|
48
|
+
fake_validation_target = OpenStruct.new(:validation_collection => [])
|
49
|
+
validation_block = lambda do
|
50
|
+
validate(:we_are_clones) {}
|
51
|
+
end # validation_block
|
52
|
+
WhyValidationsSuckIn96::ValidationBuilder.new(fake_validation_target, validation_block).create_validations!
|
53
|
+
WhyValidationsSuckIn96::ValidationBuilder.new(fake_validation_target, validation_block).create_validations!
|
54
|
+
fake_validation_target
|
55
|
+
end
|
56
|
+
|
57
|
+
should "only have one validation in the collection on the target" do
|
58
|
+
topic.validation_collection.size
|
59
|
+
end.equals(1)
|
60
|
+
|
61
|
+
end # when defining multiple validations with the same name in the one validation definition
|
62
|
+
end # validation builder
|