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,81 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta name="Content-Type" content="text/html; charset=UTF-8" />
|
6
|
+
<title>Top Level Namespace</title>
|
7
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
|
8
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
|
9
|
+
|
10
|
+
<script type="text/javascript" charset="utf-8">
|
11
|
+
relpath = '';
|
12
|
+
if (relpath != '') relpath += '/';
|
13
|
+
</script>
|
14
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
15
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
16
|
+
|
17
|
+
</head>
|
18
|
+
<body>
|
19
|
+
<div id="header">
|
20
|
+
<div id="menu">
|
21
|
+
|
22
|
+
<a href="_index.html">Index</a> »
|
23
|
+
|
24
|
+
|
25
|
+
<span class="title">Top Level Namespace</span>
|
26
|
+
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<div id="search">
|
30
|
+
<a id="class_list_link" href="#">Namespace List</a>
|
31
|
+
<a id="method_list_link" href="#">Method List</a>
|
32
|
+
<a id ="file_list_link" href="#">File List</a>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div class="clear"></div>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<iframe id="search_frame"></iframe>
|
39
|
+
|
40
|
+
<div id="content"><h1>Top Level Namespace
|
41
|
+
|
42
|
+
|
43
|
+
</h1>
|
44
|
+
|
45
|
+
<dl class="box">
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
</dl>
|
54
|
+
<div class="clear"></div>
|
55
|
+
|
56
|
+
<h2>Defined Under Namespace</h2>
|
57
|
+
<p class="children">
|
58
|
+
|
59
|
+
|
60
|
+
<strong class="modules">Modules:</strong> <a href="ActiveRecord.html" title="ActiveRecord">ActiveRecord</a>, <a href="WhyValidationsSuckIn96.html" title="WhyValidationsSuckIn96">WhyValidationsSuckIn96</a>
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
<strong class="classes">Classes:</strong> <a href="FalseClass.html" title="FalseClass">FalseClass</a>, <a href="NilClass.html" title="NilClass">NilClass</a>, <a href="Numeric.html" title="Numeric">Numeric</a>, <a href="Object.html" title="Object">Object</a>, <a href="String.html" title="String">String</a>, <a href="TrueClass.html" title="TrueClass">TrueClass</a>
|
65
|
+
|
66
|
+
|
67
|
+
</p>
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
</div>
|
73
|
+
|
74
|
+
<div id="footer">
|
75
|
+
Generated on Sun Dec 20 19:49:47 2009 by
|
76
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool">yard</a>
|
77
|
+
0.5.2 (ruby-1.8.7).
|
78
|
+
</div>
|
79
|
+
|
80
|
+
</body>
|
81
|
+
</html>
|
@@ -0,0 +1,46 @@
|
|
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
|
3
|
+
# dependency on SkippableValidation that will most likely be removed in future releases, but is something to be
|
4
|
+
# aware of currently.
|
5
|
+
module AttributeBasedValidation
|
6
|
+
|
7
|
+
# An initializer for a validation that checks to see if the required options have been passed for
|
8
|
+
# attribute based validation to work as expected.
|
9
|
+
# @param [Object] validatable An object to be validated
|
10
|
+
# @param [Hash] options The options to set up the validation with
|
11
|
+
# @option options [Symbol] :attribute The attribute on the validatable object to validate against
|
12
|
+
# @option options [true, false] :allow_nil If true, skips validation of the value of the attribute is #nil?
|
13
|
+
# @option options [true, false] :allow_blank If true, skips validation of the value of the attribute is #blank?
|
14
|
+
def initialize(validatable, options = {})
|
15
|
+
raise(ArgumentError, "The attribute to validate must be specified as :attribute") unless options[:attribute]
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
# The attribute to validate against
|
20
|
+
def attribute
|
21
|
+
options[:attribute]
|
22
|
+
end
|
23
|
+
|
24
|
+
# The value of the attribute to validate against
|
25
|
+
def attribute_value
|
26
|
+
validatable.send(options[:attribute])
|
27
|
+
end
|
28
|
+
|
29
|
+
# A default validate implementation that skips on #nil?/#blank? attribute values if :allow_nil or :allow_blank
|
30
|
+
# have been set.
|
31
|
+
def validate
|
32
|
+
skip if skip_on_blank? || skip_on_nil?
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def skip_on_nil?
|
39
|
+
options[:allow_nil] && attribute_value.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
def skip_on_blank?
|
43
|
+
options[:allow_blank] && attribute_value.blank?
|
44
|
+
end
|
45
|
+
end # AttributeBasedValidation
|
46
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Object
|
2
|
+
unless instance_methods(false).include?("blank?")
|
3
|
+
def blank?
|
4
|
+
respond_to?(:empty?) ? empty? : !self
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class String
|
10
|
+
unless instance_methods(false).include?("blank?")
|
11
|
+
def blank?
|
12
|
+
self !~ /\S/
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Numeric
|
18
|
+
unless instance_methods(false).include?("blank?")
|
19
|
+
def blank?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class TrueClass
|
26
|
+
unless instance_methods(false).include?("blank?")
|
27
|
+
def blank?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class FalseClass
|
34
|
+
unless instance_methods(false).include?("blank?")
|
35
|
+
def blank?
|
36
|
+
true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class NilClass
|
42
|
+
unless instance_methods(false).include?("blank?")
|
43
|
+
def blank?
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
2
|
+
require 'whyvalidationssuckin96/attribute_based_validation'
|
3
|
+
|
4
|
+
module WhyValidationsSuckIn96
|
5
|
+
|
6
|
+
# Validates the acceptance of an attribute, such as the "I agree to the terms and conditions" checkbox value returned
|
7
|
+
# by a form post.
|
8
|
+
#
|
9
|
+
# @example Default usage
|
10
|
+
# setup_validations do
|
11
|
+
# validates_acceptance_of :privacy_policy, :terms_and_conditions
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @example Changing the :accept value
|
15
|
+
# setup_validations do
|
16
|
+
# validates_acceptance_of :privacy_policy, :accept => "yep"
|
17
|
+
# end
|
18
|
+
class ValidatesAcceptance < Validation
|
19
|
+
DefaultOptions = {:allow_nil => true, :accept => "1", :message => "must be accepted"}
|
20
|
+
|
21
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
22
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
23
|
+
|
24
|
+
def validate
|
25
|
+
super
|
26
|
+
if options[:accept] == attribute_value
|
27
|
+
pass
|
28
|
+
else
|
29
|
+
fail
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end # Validation
|
34
|
+
|
35
|
+
ValidationBuilder.register_macro :validates_acceptance_of, WhyValidationsSuckIn96::ValidatesAcceptance
|
36
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
2
|
+
require 'whyvalidationssuckin96/attribute_based_validation'
|
3
|
+
|
4
|
+
module WhyValidationsSuckIn96
|
5
|
+
|
6
|
+
# Checks the validity of any associated objects, such as an ActiveRecord association.
|
7
|
+
#
|
8
|
+
# @example Checking the validity of an associated collection of tracks
|
9
|
+
# setup_validations do
|
10
|
+
# validates_associated :tracks
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @example Checking the validity of an associated artist
|
14
|
+
# setup_validations do
|
15
|
+
# validates_associated :artist
|
16
|
+
# end
|
17
|
+
class ValidatesAssociated < Validation
|
18
|
+
DefaultOptions = {:message => "is invalid"}
|
19
|
+
|
20
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
21
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
22
|
+
|
23
|
+
def validate
|
24
|
+
super
|
25
|
+
Array(attribute_value).collect do |assoc|
|
26
|
+
assoc.valid?
|
27
|
+
end.all? ? pass : fail
|
28
|
+
end
|
29
|
+
|
30
|
+
end # Validation
|
31
|
+
|
32
|
+
ValidationBuilder.register_macro :validates_associated, WhyValidationsSuckIn96::ValidatesAssociated
|
33
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
2
|
+
require 'whyvalidationssuckin96/attribute_based_validation'
|
3
|
+
|
4
|
+
module WhyValidationsSuckIn96
|
5
|
+
|
6
|
+
# Checks the validity of an attribute against a confirmation field. Note that this validation does
|
7
|
+
# not set up the confirmation field on the object, leaving this up to the implementer.
|
8
|
+
#
|
9
|
+
# @example Default usage
|
10
|
+
# class Account
|
11
|
+
# attr_accessor :password, :password_confirmation
|
12
|
+
# setup_validations do
|
13
|
+
# validates_confirmation_of :password
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
class ValidatesConfirmation < Validation
|
17
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
18
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
19
|
+
|
20
|
+
DefaultOptions = {:message => "does not match the confirmation"}
|
21
|
+
|
22
|
+
def validate
|
23
|
+
super
|
24
|
+
skip unless confirmation_value = validatable.send(confirmation_field)
|
25
|
+
if confirmation_value == attribute_value
|
26
|
+
pass
|
27
|
+
else
|
28
|
+
fail
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def confirmation_field
|
35
|
+
:"#{attribute}_confirmation"
|
36
|
+
end
|
37
|
+
end # Validation
|
38
|
+
|
39
|
+
ValidationBuilder.register_macro :validates_confirmation_of, WhyValidationsSuckIn96::ValidatesAcceptance
|
40
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
2
|
+
require 'whyvalidationssuckin96/attribute_based_validation'
|
3
|
+
|
4
|
+
module WhyValidationsSuckIn96
|
5
|
+
|
6
|
+
# Checks the validity of an attribute against a collection of excluded values.
|
7
|
+
#
|
8
|
+
# @example Default usage
|
9
|
+
# setup_validations do
|
10
|
+
# validates_exclusion_of :subdomain, :in => %w[www ftp]
|
11
|
+
# end
|
12
|
+
class ValidatesExclusion < Validation
|
13
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
14
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
15
|
+
|
16
|
+
DefaultOptions = {:message => "is in the excluded collection"}
|
17
|
+
|
18
|
+
# @param [Object] validatable An object to be validated.
|
19
|
+
# @param [Hash] options The options to set up the validation with.
|
20
|
+
# @option options [#include?] :in A collection to check against for exclusion.
|
21
|
+
def initialize(validatable, options = {})
|
22
|
+
super
|
23
|
+
raise(ArgumentError, "Collection to check for exclusion against should be specified with :in") unless options[:in]
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate
|
27
|
+
super
|
28
|
+
if options[:in].include?(attribute_value)
|
29
|
+
fail
|
30
|
+
else
|
31
|
+
pass
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end # Validation
|
36
|
+
|
37
|
+
ValidationBuilder.register_macro :validates_exclusion_of, WhyValidationsSuckIn96::ValidatesExclusion
|
38
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
2
|
+
require 'whyvalidationssuckin96/attribute_based_validation'
|
3
|
+
|
4
|
+
module WhyValidationsSuckIn96
|
5
|
+
|
6
|
+
# Checks the validity of an attribute against a regular expression.
|
7
|
+
#
|
8
|
+
# @example Default usage
|
9
|
+
# setup_validations do
|
10
|
+
# validates_format_of :username, :with => /[a-z0-9]/i
|
11
|
+
# end
|
12
|
+
class ValidatesFormat < Validation
|
13
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
14
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
15
|
+
|
16
|
+
DefaultOptions = {:message => "does not match the given format"}
|
17
|
+
|
18
|
+
# @param [Object] validatable An object to be validated
|
19
|
+
# @param [Hash] options The options to set up the validation with
|
20
|
+
# @option options [Regexp] :with A regular expression to check against
|
21
|
+
def initialize(validatable, options = {})
|
22
|
+
super
|
23
|
+
raise(ArgumentError, "Regular expression to check against must be given as :with") unless options[:with]
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate
|
27
|
+
super
|
28
|
+
if attribute_value.to_s =~ options[:with]
|
29
|
+
pass
|
30
|
+
else
|
31
|
+
fail
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end # Validation
|
36
|
+
|
37
|
+
ValidationBuilder.register_macro :validates_format_of, WhyValidationsSuckIn96::ValidatesFormat
|
38
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
2
|
+
require 'whyvalidationssuckin96/attribute_based_validation'
|
3
|
+
|
4
|
+
module WhyValidationsSuckIn96
|
5
|
+
|
6
|
+
# Checks the validity of an attribute against a list of values for it to be included in.
|
7
|
+
#
|
8
|
+
# @example Default usage
|
9
|
+
# setup_validations do
|
10
|
+
# validates_inclusion_of :unit_system, :in => %w[imperial metric]
|
11
|
+
# end
|
12
|
+
class ValidatesInclusion < Validation
|
13
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
14
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
15
|
+
|
16
|
+
DefaultOptions = {:message => "is not in the acceptable collection"}
|
17
|
+
|
18
|
+
# @param [Object] validatable An object to be validated.
|
19
|
+
# @param [Hash] options The options to set up the validation with.
|
20
|
+
# @option options [#include?] :in A collection to check against for inclusion.
|
21
|
+
def initialize(validatable, options = {})
|
22
|
+
super
|
23
|
+
raise(ArgumentError, "Collection to check for inclusion against should be specified with :in") unless options[:in]
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate
|
27
|
+
super
|
28
|
+
if options[:in].include?(attribute_value)
|
29
|
+
pass
|
30
|
+
else
|
31
|
+
fail
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end # Validation
|
36
|
+
|
37
|
+
ValidationBuilder.register_macro :validates_inclusion_of, WhyValidationsSuckIn96::ValidatesInclusion
|
38
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
2
|
+
require 'whyvalidationssuckin96/attribute_based_validation'
|
3
|
+
|
4
|
+
module WhyValidationsSuckIn96
|
5
|
+
|
6
|
+
# Checks the validity of an attribute against a given set of sizes.
|
7
|
+
#
|
8
|
+
# @example Checking against an exact value
|
9
|
+
# setup_validations do
|
10
|
+
# validates_length_of :choices, :is => 4
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @example Checking against a range
|
14
|
+
# setup_validations do
|
15
|
+
# validates_length_of :choices, :in => 1..10
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# @example Checking against a minimum value
|
19
|
+
# setup_validations do
|
20
|
+
# validates_length_of :choices, :minimum => 1
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# @example Checking against a maximum value
|
24
|
+
# setup_validations do
|
25
|
+
# validates_length_of :choices, :maximum => 10
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @example Checking against a minimum and maximum value
|
29
|
+
# setup_validations do
|
30
|
+
# validates_length_of :choices, :minimum => 1, :maximum => 10
|
31
|
+
# end
|
32
|
+
class ValidatesLength < Validation
|
33
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
34
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
35
|
+
|
36
|
+
DefaultOptions = {:message => "does not meet the given length restrictions"}
|
37
|
+
ValidOptions = [:is, :in, :minimum, :maximum]
|
38
|
+
OptionIncompatibility = {
|
39
|
+
:is => [:minimum, :maximum, :in],
|
40
|
+
:in => [:minimum, :maximum, :is]
|
41
|
+
}
|
42
|
+
|
43
|
+
# @param [Object] validatable An object to be validated.
|
44
|
+
# @param [Hash] options The options to set up the validation with.
|
45
|
+
# @option options [#==] :is An exact value to check the validatable object's #size against.
|
46
|
+
# @option options [#include?] :in A range to check the validatable object's #size against.
|
47
|
+
# @option options [#<=] :minimum A minimum value to check the validatable object's size against.
|
48
|
+
# @option options [#>=] :maximum A maximum value to check the validatable object's size against.
|
49
|
+
def initialize(validatable, options = {})
|
50
|
+
super
|
51
|
+
check_options(options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate
|
55
|
+
super
|
56
|
+
all_valid = ValidOptions.collect do |opt_name|
|
57
|
+
next(true) if options[opt_name].nil?
|
58
|
+
send(:"validate_#{opt_name}")
|
59
|
+
end.all?
|
60
|
+
all_valid ? pass : fail
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def validate_is
|
66
|
+
options[:is] == attribute_value.size
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate_in
|
70
|
+
options[:in].include?(attribute_value.size)
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate_minimum
|
74
|
+
options[:minimum] <= attribute_value.size
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate_maximum
|
78
|
+
options[:maximum] >= attribute_value.size
|
79
|
+
end
|
80
|
+
|
81
|
+
def check_options(options_hash)
|
82
|
+
OptionIncompatibility.each do |opt,incompat|
|
83
|
+
next unless options_hash[opt]
|
84
|
+
bad_opt = incompat.detect { |opt_name| options_hash.keys.include?(opt_name) }
|
85
|
+
if bad_opt
|
86
|
+
names = [opt.inspect.to_s, bad_opt.inspect.to_s].sort
|
87
|
+
raise(ArgumentError, "Option #{names.first} can not be mixed with #{names.last}")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
raise(ArgumentError, "Length options must be given as :minimum, :maximum, :is, or :in") unless options_hash.keys.any? do |opt|
|
91
|
+
ValidOptions.include?(opt)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end # Validation
|
96
|
+
|
97
|
+
ValidationBuilder.register_macro :validates_length_of, WhyValidationsSuckIn96::ValidatesLength
|
98
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
2
|
+
require 'whyvalidationssuckin96/attribute_based_validation'
|
3
|
+
|
4
|
+
module WhyValidationsSuckIn96
|
5
|
+
|
6
|
+
# Checks to see if a given attribute is a valid numerical value. Allows a certain degree of latitude in determining
|
7
|
+
# what is a valid numerical value, like allowing commas and spaces in the value for example.
|
8
|
+
#
|
9
|
+
# @example Default usage
|
10
|
+
# setup_validations do
|
11
|
+
# validates_numericality_of :cost
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @example Only allow integer values
|
15
|
+
# setup_validations do
|
16
|
+
# validates_numericality_of :cost, :only_integer => true
|
17
|
+
# end
|
18
|
+
class ValidatesNumericality < Validation
|
19
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
20
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
21
|
+
|
22
|
+
DefaultOptions = {:message => "is not a numerical value"}
|
23
|
+
StripNonNumeric = /[^-+e\d.]/im
|
24
|
+
ValidNumericChars = /\A[-+e\d.,\s]+\Z/im
|
25
|
+
|
26
|
+
def validate
|
27
|
+
super
|
28
|
+
if options[:only_integer]
|
29
|
+
validate_as_integer
|
30
|
+
else
|
31
|
+
validate_as_float
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def validate_as_integer
|
38
|
+
fail if attribute_value.to_s !~ ValidNumericChars
|
39
|
+
Integer(attribute_value.to_s.gsub(StripNonNumeric, ""))
|
40
|
+
pass
|
41
|
+
rescue ArgumentError, TypeError
|
42
|
+
fail
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_as_float
|
46
|
+
fail if attribute_value.to_s !~ ValidNumericChars
|
47
|
+
Kernel.Float(attribute_value.to_s.gsub(StripNonNumeric, ""))
|
48
|
+
pass
|
49
|
+
rescue ArgumentError, TypeError
|
50
|
+
fail
|
51
|
+
end
|
52
|
+
|
53
|
+
end # Validation
|
54
|
+
|
55
|
+
ValidationBuilder.register_macro :validates_numericality_of, WhyValidationsSuckIn96::ValidatesNumericality
|
56
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'whyvalidationssuckin96/skippable_validation'
|
2
|
+
require 'whyvalidationssuckin96/attribute_based_validation'
|
3
|
+
|
4
|
+
module WhyValidationsSuckIn96
|
5
|
+
|
6
|
+
# Checks for the presence of a given attribute.
|
7
|
+
#
|
8
|
+
# @example Default usage
|
9
|
+
# setup_validations do
|
10
|
+
# validates_presence_of :name
|
11
|
+
# end
|
12
|
+
class ValidatesPresence < Validation
|
13
|
+
include WhyValidationsSuckIn96::SkippableValidation
|
14
|
+
include WhyValidationsSuckIn96::AttributeBasedValidation
|
15
|
+
|
16
|
+
DefaultOptions = {:message => "is not present"}
|
17
|
+
|
18
|
+
def validate
|
19
|
+
super
|
20
|
+
if attribute_value.blank?
|
21
|
+
fail
|
22
|
+
else
|
23
|
+
pass
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end # Validation
|
28
|
+
|
29
|
+
ValidationBuilder.register_macro :validates_presence_of, WhyValidationsSuckIn96::ValidatesPresence
|
30
|
+
end # WhyValidationsSuckIn96
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'whyvalidationssuckin96/macros/validates_acceptance'
|
2
|
+
require 'whyvalidationssuckin96/macros/validates_associated'
|
3
|
+
require 'whyvalidationssuckin96/macros/validates_confirmation'
|
4
|
+
require 'whyvalidationssuckin96/macros/validates_exclusion'
|
5
|
+
require 'whyvalidationssuckin96/macros/validates_format'
|
6
|
+
require 'whyvalidationssuckin96/macros/validates_inclusion'
|
7
|
+
require 'whyvalidationssuckin96/macros/validates_length'
|
8
|
+
require 'whyvalidationssuckin96/macros/validates_numericality'
|
9
|
+
require 'whyvalidationssuckin96/macros/validates_presence'
|