durran-validatable 1.7.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +118 -0
- data/Rakefile +55 -0
- data/VERSION.yml +4 -0
- data/lib/child_validation.rb +15 -0
- data/lib/errors.rb +90 -0
- data/lib/included_validation.rb +9 -0
- data/lib/macros.rb +306 -0
- data/lib/object_extension.rb +21 -0
- data/lib/requireable.rb +26 -0
- data/lib/understandable.rb +31 -0
- data/lib/validatable.rb +25 -0
- data/lib/validatable_class_methods.rb +85 -0
- data/lib/validatable_instance_methods.rb +116 -0
- data/lib/validations/validates_acceptance_of.rb +14 -0
- data/lib/validations/validates_associated.rb +13 -0
- data/lib/validations/validates_confirmation_of.rb +23 -0
- data/lib/validations/validates_each.rb +14 -0
- data/lib/validations/validates_format_of.rb +16 -0
- data/lib/validations/validates_length_of.rb +30 -0
- data/lib/validations/validates_numericality_of.rb +27 -0
- data/lib/validations/validates_presence_of.rb +17 -0
- data/lib/validations/validates_true_for.rb +13 -0
- data/lib/validations/validation_base.rb +91 -0
- data/test/all_tests.rb +1 -0
- data/test/functional/test_validatable.rb +589 -0
- data/test/functional/test_validates_acceptance_of.rb +16 -0
- data/test/functional/test_validates_associated.rb +41 -0
- data/test/functional/test_validates_confirmation_of.rb +56 -0
- data/test/functional/test_validates_each.rb +14 -0
- data/test/functional/test_validates_format_of.rb +34 -0
- data/test/functional/test_validates_length_of.rb +64 -0
- data/test/functional/test_validates_numericality_of.rb +57 -0
- data/test/functional/test_validates_presence_of.rb +16 -0
- data/test/functional/test_validates_true_for.rb +27 -0
- data/test/test_helper.rb +33 -0
- data/test/unit/test_errors.rb +70 -0
- data/test/unit/test_understandable.rb +19 -0
- data/test/unit/test_validatable.rb +38 -0
- data/test/unit/test_validates_acceptance_of.rb +45 -0
- data/test/unit/test_validates_associated.rb +29 -0
- data/test/unit/test_validates_confirmation_of.rb +76 -0
- data/test/unit/test_validates_format_of.rb +44 -0
- data/test/unit/test_validates_length_of.rb +80 -0
- data/test/unit/test_validates_numericality_of.rb +76 -0
- data/test/unit/test_validates_presence_of.rb +35 -0
- data/test/unit/test_validates_true_for.rb +29 -0
- data/test/unit/test_validation_base.rb +52 -0
- metadata +126 -0
data/README.rdoc
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
= Validatable
|
2
|
+
|
3
|
+
Validatable is a library for adding validations.
|
4
|
+
|
5
|
+
by Jay[http://jayfields.blogspot.com] Fields[http://jayfields.blogspot.com]
|
6
|
+
|
7
|
+
== Download and Installation
|
8
|
+
|
9
|
+
You can download Validatable from here[http://rubyforge.org/projects/validatable] or install it with the following command.
|
10
|
+
|
11
|
+
$ gem install validatable
|
12
|
+
|
13
|
+
== License
|
14
|
+
|
15
|
+
You may use, copy and redistribute this library under the same terms as Ruby itself (see http://www.ruby-lang.org/en/LICENSE.txt).
|
16
|
+
|
17
|
+
== Examples
|
18
|
+
|
19
|
+
Validation of an entire hierarchy of objects with errors aggregated at the root object.
|
20
|
+
|
21
|
+
class Person
|
22
|
+
include Validatable
|
23
|
+
validates_presence_of :name
|
24
|
+
attr_accessor :name
|
25
|
+
end
|
26
|
+
|
27
|
+
class PersonPresenter
|
28
|
+
include Validatable
|
29
|
+
include_validations_for :person
|
30
|
+
attr_accessor :person
|
31
|
+
|
32
|
+
def initialize(person)
|
33
|
+
@person = person
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
presenter = PersonPresenter.new(Person.new)
|
38
|
+
presenter.valid? #=> false
|
39
|
+
presenter.errors.on(:name) #=> "can't be blank"
|
40
|
+
|
41
|
+
Validations that turn off after X times of failed attempts.
|
42
|
+
|
43
|
+
class Person
|
44
|
+
include Validatable
|
45
|
+
validates_presence_of :name, :times => 1
|
46
|
+
attr_accessor :name
|
47
|
+
end
|
48
|
+
|
49
|
+
person = Person.new
|
50
|
+
person.valid? #=> false
|
51
|
+
person.valid? #=> true
|
52
|
+
|
53
|
+
Validations can be given levels. If a validation fails on a level the validations for subsequent levels will not be executed.
|
54
|
+
|
55
|
+
class Person
|
56
|
+
include Validatable
|
57
|
+
validates_presence_of :name, :level => 1, :message => "name message"
|
58
|
+
validates_presence_of :address, :level => 2
|
59
|
+
attr_accessor :name, :address
|
60
|
+
end
|
61
|
+
|
62
|
+
person = Person.new
|
63
|
+
person.valid? #=> false
|
64
|
+
person.errors.on(:name) #=> "name message"
|
65
|
+
person.errors.on(:address) #=> nil
|
66
|
+
|
67
|
+
Validations can also be given groups. Groups can be used to validate an object when it can be valid in various states. For example a mortgage application may be valid for saving (saving a partial application), but that same mortgage application would not be valid for underwriting. In our example a application can be saved as long as a Social Security Number is present; however, an application can not be underwritten unless the name attribute contains a value.
|
68
|
+
|
69
|
+
class MortgageApplication
|
70
|
+
include Validatable
|
71
|
+
validates_presence_of :ssn, :groups => [:saving, :underwriting]
|
72
|
+
validates_presence_of :name, :groups => :underwriting
|
73
|
+
attr_accessor :name, :ssn
|
74
|
+
end
|
75
|
+
|
76
|
+
application = MortgageApplication.new
|
77
|
+
application.ssn = 377990118
|
78
|
+
application.valid_for_saving? #=> true
|
79
|
+
application.valid_for_underwriting? #=> false
|
80
|
+
|
81
|
+
As you can see, you can use an array if the validation needs to be part of various groups. However, if the validation only applies to one group you can simply use a symbol for the group name.
|
82
|
+
|
83
|
+
Similar to Rails, Validatable also supports conditional validation.
|
84
|
+
|
85
|
+
class Person
|
86
|
+
include Validatable
|
87
|
+
attr_accessor :name
|
88
|
+
validates_format_of :name, :with => /.+/, :if => Proc.new { !name.nil? }
|
89
|
+
end
|
90
|
+
Person.new.valid? #=> true
|
91
|
+
|
92
|
+
Validatable also exposes an after_validate hook method.
|
93
|
+
|
94
|
+
class Person
|
95
|
+
include Validatable
|
96
|
+
validates_presence_of :name
|
97
|
+
attr_accessor :name
|
98
|
+
end
|
99
|
+
|
100
|
+
class ValidatesPresenceOf
|
101
|
+
after_validate do |result, instance, attribute|
|
102
|
+
instance.errors.add("#{attribute} can't be blank") unless result
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
person = Person.new
|
107
|
+
person.valid? #=> false
|
108
|
+
person.errors.on(:name) #=> "name can't be blank"
|
109
|
+
|
110
|
+
The after_validate hook yields the result of the validation being run,
|
111
|
+
the instance the validation was run on, and the attribute that was validated
|
112
|
+
|
113
|
+
In the above example the attribute "name" is appended to the message.
|
114
|
+
|
115
|
+
See the tests for more examples
|
116
|
+
|
117
|
+
== Contributors
|
118
|
+
Rick Bradley, Anonymous Z, Jason Miller, Ali Aghareza, Xavier Shay, Dan Manges, Karthik Krishnan and Venkat, Clint Bishop, Chris Didyk, Yi Wen
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "durran-validatable"
|
8
|
+
gem.summary = %Q{Validatable is a library for adding validations.}
|
9
|
+
gem.email = "durran@gmail.com"
|
10
|
+
gem.homepage = "http://github.com/durran/validatable"
|
11
|
+
gem.authors = ['Jay Fields', 'John Nunemaker', 'Durran Jordan']
|
12
|
+
gem.files = FileList['lib/**/*.rb', '[A-Z]*', 'test/**/*'].to_a
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/test_*.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :default => :test
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
if File.exist?('VERSION.yml')
|
45
|
+
config = YAML.load(File.read('VERSION.yml'))
|
46
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
47
|
+
else
|
48
|
+
version = ""
|
49
|
+
end
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "validatable #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Validatable
|
2
|
+
class ChildValidation #:nodoc:
|
3
|
+
attr_accessor :attribute, :map, :should_validate_proc
|
4
|
+
|
5
|
+
def initialize(attribute, map, should_validate_proc)
|
6
|
+
@attribute = attribute
|
7
|
+
@map = map
|
8
|
+
@should_validate_proc = should_validate_proc
|
9
|
+
end
|
10
|
+
|
11
|
+
def should_validate?(instance)
|
12
|
+
instance.instance_eval &should_validate_proc
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/errors.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module Validatable
|
2
|
+
class Errors
|
3
|
+
extend Forwardable
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def_delegators :errors, :clear, :each, :each_pair, :empty?, :length, :size
|
7
|
+
|
8
|
+
# Returns true if the specified +attribute+ has errors associated with it.
|
9
|
+
#
|
10
|
+
# class Company < ActiveRecord::Base
|
11
|
+
# validates_presence_of :name, :address, :email
|
12
|
+
# validates_length_of :name, :in => 5..30
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# company = Company.create(:address => '123 First St.')
|
16
|
+
# company.errors.invalid?(:name) # => true
|
17
|
+
# company.errors.invalid?(:address) # => false
|
18
|
+
def invalid?(attribute)
|
19
|
+
!@errors[attribute.to_sym].nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
# call-seq: on(attribute)
|
23
|
+
#
|
24
|
+
# * Returns nil, if no errors are associated with the specified +attribute+.
|
25
|
+
# * Returns the error message, if one error is associated with the specified +attribute+.
|
26
|
+
# * Returns an array of error messages, if more than one error is associated with the specified +attribute+.
|
27
|
+
def on(attribute)
|
28
|
+
return nil if errors[attribute.to_sym].nil?
|
29
|
+
errors[attribute.to_sym].size == 1 ? errors[attribute.to_sym].first : errors[attribute.to_sym]
|
30
|
+
end
|
31
|
+
|
32
|
+
alias [] on
|
33
|
+
|
34
|
+
def add(attribute, message) #:nodoc:
|
35
|
+
errors[attribute.to_sym] = [] if errors[attribute.to_sym].nil?
|
36
|
+
errors[attribute.to_sym] << message
|
37
|
+
end
|
38
|
+
|
39
|
+
def merge!(errors) #:nodoc:
|
40
|
+
errors.each_pair{|k, v| add(k,v)}
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# call-seq: replace(attribute)
|
45
|
+
#
|
46
|
+
# * Replaces the errors value for the given +attribute+
|
47
|
+
def replace(attribute, value)
|
48
|
+
errors[attribute.to_sym] = value
|
49
|
+
end
|
50
|
+
|
51
|
+
# call-seq: raw(attribute)
|
52
|
+
#
|
53
|
+
# * Returns an array of error messages associated with the specified +attribute+.
|
54
|
+
def raw(attribute)
|
55
|
+
errors[attribute.to_sym]
|
56
|
+
end
|
57
|
+
|
58
|
+
def errors #:nodoc:
|
59
|
+
@errors ||= {}
|
60
|
+
end
|
61
|
+
|
62
|
+
def count #:nodoc:
|
63
|
+
errors.values.flatten.size
|
64
|
+
end
|
65
|
+
|
66
|
+
# call-seq: full_messages -> an_array_of_messages
|
67
|
+
#
|
68
|
+
# Returns an array containing the full list of error messages.
|
69
|
+
def full_messages
|
70
|
+
full_messages = []
|
71
|
+
|
72
|
+
errors.each_key do |attribute|
|
73
|
+
errors[attribute].each do |msg|
|
74
|
+
next if msg.nil?
|
75
|
+
|
76
|
+
if attribute.to_s == "base"
|
77
|
+
full_messages << msg
|
78
|
+
else
|
79
|
+
full_messages << humanize(attribute.to_s) + " " + msg
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
full_messages
|
84
|
+
end
|
85
|
+
|
86
|
+
def humanize(lower_case_and_underscored_word) #:nodoc:
|
87
|
+
lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/macros.rb
ADDED
@@ -0,0 +1,306 @@
|
|
1
|
+
module Validatable
|
2
|
+
module Macros
|
3
|
+
# call-seq: validates_each(*args)
|
4
|
+
#
|
5
|
+
# Validates that the logic evaluates to true
|
6
|
+
#
|
7
|
+
# class Address
|
8
|
+
# include Validatable
|
9
|
+
# validates_each :zip_code, :logic => lambda { errors.add(:zip_code, "is not valid") if ZipCodeService.allows(zip_code) }
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# The logic option is required.
|
13
|
+
#
|
14
|
+
# Configuration options:
|
15
|
+
#
|
16
|
+
# * after_validate - A block that executes following the run of a validation
|
17
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
18
|
+
# * if - A block that when executed must return true of the validation will not occur
|
19
|
+
# * level - The level at which the validation should occur
|
20
|
+
# * logic - A block that executes to perform the validation
|
21
|
+
# * message - The message to add to the errors collection when the validation fails
|
22
|
+
# * times - The number of times the validation applies
|
23
|
+
def validates_each(*args)
|
24
|
+
add_validations(args, ValidatesEach)
|
25
|
+
end
|
26
|
+
|
27
|
+
# call-seq: validates_format_of(*args)
|
28
|
+
#
|
29
|
+
# Validates whether the value of the specified attribute is of the
|
30
|
+
# correct form by matching it against the regular expression provided.
|
31
|
+
#
|
32
|
+
# class Person
|
33
|
+
# include Validatable
|
34
|
+
# validates_format_of :first_name, :with => /[ A-Za-z]/
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# A regular expression must be provided or else an exception will be raised.
|
38
|
+
#
|
39
|
+
# Configuration options:
|
40
|
+
#
|
41
|
+
# * after_validate - A block that executes following the run of a validation
|
42
|
+
# * message - The message to add to the errors collection when the validation fails
|
43
|
+
# * times - The number of times the validation applies
|
44
|
+
# * level - The level at which the validation should occur
|
45
|
+
# * if - A block that when executed must return true of the validation will not occur
|
46
|
+
# * with - The regular expression used to validate the format
|
47
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
48
|
+
def validates_format_of(*args)
|
49
|
+
add_validations(args, ValidatesFormatOf)
|
50
|
+
end
|
51
|
+
|
52
|
+
# call-seq: validates_length_of(*args)
|
53
|
+
#
|
54
|
+
# Validates that the specified attribute matches the length restrictions supplied.
|
55
|
+
#
|
56
|
+
# class Person
|
57
|
+
# include Validatable
|
58
|
+
# validates_length_of :first_name, :maximum=>30
|
59
|
+
# validates_length_of :last_name, :minimum=>30
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# Configuration options:
|
63
|
+
#
|
64
|
+
# * after_validate - A block that executes following the run of a validation
|
65
|
+
# * message - The message to add to the errors collection when the validation fails
|
66
|
+
# * times - The number of times the validation applies
|
67
|
+
# * level - The level at which the validation should occur
|
68
|
+
# * if - A block that when executed must return true of the validation will not occur
|
69
|
+
# * minimum - The minimum size of the attribute
|
70
|
+
# * maximum - The maximum size of the attribute
|
71
|
+
# * is - The size the attribute must be
|
72
|
+
# * within - A range that the size of the attribute must fall within
|
73
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
74
|
+
def validates_length_of(*args)
|
75
|
+
add_validations(args, ValidatesLengthOf)
|
76
|
+
end
|
77
|
+
|
78
|
+
# call-seq: validates_numericality_of(*args)
|
79
|
+
#
|
80
|
+
# Validates that the specified attribute is numeric.
|
81
|
+
#
|
82
|
+
# class Person
|
83
|
+
# include Validatable
|
84
|
+
# validates_numericality_of :age
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# Configuration options:
|
88
|
+
#
|
89
|
+
# * after_validate - A block that executes following the run of a validation
|
90
|
+
# * message - The message to add to the errors collection when the validation fails
|
91
|
+
# * times - The number of times the validation applies
|
92
|
+
# * level - The level at which the validation should occur
|
93
|
+
# * if - A block that when executed must return true of the validation will not occur
|
94
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
95
|
+
# * only_integer - Whether the attribute must be an integer (default is false)
|
96
|
+
def validates_numericality_of(*args)
|
97
|
+
add_validations(args, ValidatesNumericalityOf)
|
98
|
+
end
|
99
|
+
|
100
|
+
# call-seq: validates_acceptance_of(*args)
|
101
|
+
#
|
102
|
+
# Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example:
|
103
|
+
#
|
104
|
+
# class Person
|
105
|
+
# include Validatable
|
106
|
+
# validates_acceptance_of :terms_of_service
|
107
|
+
# validates_acceptance_of :eula, :message => "must be abided"
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# Configuration options:
|
111
|
+
#
|
112
|
+
# * after_validate - A block that executes following the run of a validation
|
113
|
+
# * message - The message to add to the errors collection when the validation fails
|
114
|
+
# * times - The number of times the validation applies
|
115
|
+
# * level - The level at which the validation should occur
|
116
|
+
# * if - A block that when executed must return true of the validation will not occur
|
117
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
118
|
+
def validates_acceptance_of(*args)
|
119
|
+
add_validations(args, ValidatesAcceptanceOf)
|
120
|
+
end
|
121
|
+
|
122
|
+
# call-seq: validates_confirmation_of(*args)
|
123
|
+
#
|
124
|
+
# Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example:
|
125
|
+
#
|
126
|
+
# Class:
|
127
|
+
# class PersonPresenter
|
128
|
+
# include Validatable
|
129
|
+
# validates_confirmation_of :user_name, :password
|
130
|
+
# validates_confirmation_of :email_address, :message => "should match confirmation"
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# View:
|
134
|
+
# <%= password_field "person", "password" %>
|
135
|
+
# <%= password_field "person", "password_confirmation" %>
|
136
|
+
#
|
137
|
+
# Configuration options:
|
138
|
+
#
|
139
|
+
# * after_validate - A block that executes following the run of a validation
|
140
|
+
# * case_sensitive - Whether or not to apply case-sensitivity on the comparison. Defaults to true.
|
141
|
+
# * message - The message to add to the errors collection when the validation fails
|
142
|
+
# * times - The number of times the validation applies
|
143
|
+
# * level - The level at which the validation should occur
|
144
|
+
# * if - A block that when executed must return true of the validation will not occur
|
145
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
146
|
+
def validates_confirmation_of(*args)
|
147
|
+
add_validations(args, ValidatesConfirmationOf)
|
148
|
+
end
|
149
|
+
|
150
|
+
# call-seq: validates_presence_of(*args)
|
151
|
+
#
|
152
|
+
# Validates that the specified attributes are not nil or an empty string
|
153
|
+
#
|
154
|
+
# class Person
|
155
|
+
# include Validatable
|
156
|
+
# validates_presence_of :first_name
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# The first_name attribute must be in the object and it cannot be nil or empty.
|
160
|
+
#
|
161
|
+
# Configuration options:
|
162
|
+
#
|
163
|
+
# * after_validate - A block that executes following the run of a validation
|
164
|
+
# * message - The message to add to the errors collection when the validation fails
|
165
|
+
# * times - The number of times the validation applies
|
166
|
+
# * level - The level at which the validation should occur
|
167
|
+
# * if - A block that when executed must return true of the validation will not occur
|
168
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
169
|
+
def validates_presence_of(*args)
|
170
|
+
add_validations(args, ValidatesPresenceOf)
|
171
|
+
end
|
172
|
+
|
173
|
+
# call-seq: validates_true_for(*args)
|
174
|
+
#
|
175
|
+
# Validates that the logic evaluates to true
|
176
|
+
#
|
177
|
+
# class Person
|
178
|
+
# include Validatable
|
179
|
+
# validates_true_for :first_name, :logic => lambda { first_name == 'Jamie' }
|
180
|
+
# end
|
181
|
+
#
|
182
|
+
# The logic option is required.
|
183
|
+
#
|
184
|
+
# Configuration options:
|
185
|
+
#
|
186
|
+
# * after_validate - A block that executes following the run of a validation
|
187
|
+
# * message - The message to add to the errors collection when the validation fails
|
188
|
+
# * times - The number of times the validation applies
|
189
|
+
# * level - The level at which the validation should occur
|
190
|
+
# * if - A block that when executed must return true of the validation will not occur
|
191
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
192
|
+
# * logic - A block that executes to perform the validation
|
193
|
+
def validates_true_for(*args)
|
194
|
+
add_validations(args, ValidatesTrueFor)
|
195
|
+
end
|
196
|
+
|
197
|
+
# call-seq: validates_associated(*args)
|
198
|
+
#
|
199
|
+
# Checks the validity of an associated object or objects and adds a single
|
200
|
+
# error if validation fails.
|
201
|
+
#
|
202
|
+
# class Person
|
203
|
+
# include Validatable
|
204
|
+
# attr_accessor :addresses
|
205
|
+
# validates_associated :addresses
|
206
|
+
# end
|
207
|
+
#
|
208
|
+
# Configuration options:
|
209
|
+
#
|
210
|
+
# * after_validate - A block that executes following the run of a validation
|
211
|
+
# * message - The message to add to the errors collection when the validation fails
|
212
|
+
# * times - The number of times the validation applies
|
213
|
+
# * level - The level at which the validation should occur
|
214
|
+
# * if - A block that when executed must return true of the validation will not occur
|
215
|
+
# * group - The group that this validation belongs to. A validation can belong to multiple groups
|
216
|
+
def validates_associated(*args)
|
217
|
+
add_validations(args, ValidatesAssociated)
|
218
|
+
end
|
219
|
+
|
220
|
+
# call-seq: include_validations_from(attribute)
|
221
|
+
#
|
222
|
+
# Includes all the validations that are defined on the attribute.
|
223
|
+
# class Person
|
224
|
+
# include Validatable
|
225
|
+
# validates_presence_of :name
|
226
|
+
# end
|
227
|
+
#
|
228
|
+
# class PersonPresenter
|
229
|
+
# include Validatable
|
230
|
+
# include_validataions_from :person
|
231
|
+
# attr_accessor :person
|
232
|
+
# def name
|
233
|
+
# person.name
|
234
|
+
# end
|
235
|
+
#
|
236
|
+
# def initialize(person)
|
237
|
+
# @person = person
|
238
|
+
# end
|
239
|
+
# end
|
240
|
+
#
|
241
|
+
# presenter = PersonPresenter.new(Person.new)
|
242
|
+
# presenter.valid? #=> false
|
243
|
+
# presenter.errors.on(:name) #=> "can't be blank"
|
244
|
+
#
|
245
|
+
# The name attribute whose validations should be added.
|
246
|
+
def include_validations_from(attribute_to_validate, options = {})
|
247
|
+
validations_to_include << IncludedValidation.new(attribute_to_validate)
|
248
|
+
end
|
249
|
+
|
250
|
+
# call-seq: include_errors_from(attribute_to_validate, options = {})
|
251
|
+
#
|
252
|
+
# Validates the specified attributes.
|
253
|
+
# class Person
|
254
|
+
# include Validatable
|
255
|
+
# validates_presence_of :name
|
256
|
+
# attr_accessor :name
|
257
|
+
# end
|
258
|
+
#
|
259
|
+
# class PersonPresenter
|
260
|
+
# include Validatable
|
261
|
+
# include_errors_from :person, :map => { :name => :namen }, :if => lambda { not person.nil? }
|
262
|
+
# attr_accessor :person
|
263
|
+
#
|
264
|
+
# def initialize(person)
|
265
|
+
# @person = person
|
266
|
+
# end
|
267
|
+
# end
|
268
|
+
#
|
269
|
+
# presenter = PersonPresenter.new(Person.new)
|
270
|
+
# presenter.valid? #=> false
|
271
|
+
# presenter.errors.on(:namen) #=> "can't be blank"
|
272
|
+
#
|
273
|
+
# The person attribute will be validated.
|
274
|
+
# If person is invalid the errors will be added to the PersonPresenter errors collection.
|
275
|
+
#
|
276
|
+
# Configuration options:
|
277
|
+
#
|
278
|
+
# * map - A hash that maps attributes of the child to attributes of the parent.
|
279
|
+
# * if - A block that when executed must return true of the validation will not occur.
|
280
|
+
def include_errors_from(attribute_to_validate, options = {})
|
281
|
+
children_to_validate << ChildValidation.new(attribute_to_validate, options[:map] || {}, options[:if] || lambda { true })
|
282
|
+
end
|
283
|
+
|
284
|
+
def include_validations_for(attribute_to_validate, options = {}) #:nodoc:
|
285
|
+
puts "include_validations_for is deprecated; use include_errors_from instead"
|
286
|
+
children_to_validate << ChildValidation.new(attribute_to_validate, options[:map] || {}, options[:if] || lambda { true })
|
287
|
+
end
|
288
|
+
|
289
|
+
# call-seq: before_validation(&block)
|
290
|
+
#
|
291
|
+
# Is called before valid? or valid_for_*?
|
292
|
+
#
|
293
|
+
# class Person
|
294
|
+
# include Validatable
|
295
|
+
# before_validation do
|
296
|
+
# self.name = "default name"
|
297
|
+
# end
|
298
|
+
#
|
299
|
+
# attr_accessor :name
|
300
|
+
# end
|
301
|
+
#
|
302
|
+
def before_validation(&block)
|
303
|
+
before_validations << block
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|