ardm-validations 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/.travis.yml +11 -0
- data/Gemfile +51 -0
- data/LICENSE +21 -0
- data/README.rdoc +122 -0
- data/Rakefile +4 -0
- data/ardm-validations.gemspec +28 -0
- data/lib/ardm-validations.rb +1 -0
- data/lib/dm-validations.rb +169 -0
- data/lib/dm-validations/auto_validate.rb +252 -0
- data/lib/dm-validations/context.rb +66 -0
- data/lib/dm-validations/contextual_validators.rb +220 -0
- data/lib/dm-validations/exceptions.rb +5 -0
- data/lib/dm-validations/formats/email.rb +65 -0
- data/lib/dm-validations/formats/url.rb +27 -0
- data/lib/dm-validations/support/object.rb +18 -0
- data/lib/dm-validations/support/ordered_hash.rb +434 -0
- data/lib/dm-validations/validation_errors.rb +137 -0
- data/lib/dm-validations/validators/absent_field_validator.rb +58 -0
- data/lib/dm-validations/validators/acceptance_validator.rb +79 -0
- data/lib/dm-validations/validators/block_validator.rb +61 -0
- data/lib/dm-validations/validators/confirmation_validator.rb +92 -0
- data/lib/dm-validations/validators/format_validator.rb +124 -0
- data/lib/dm-validations/validators/generic_validator.rb +184 -0
- data/lib/dm-validations/validators/length_validator.rb +249 -0
- data/lib/dm-validations/validators/method_validator.rb +64 -0
- data/lib/dm-validations/validators/numeric_validator.rb +182 -0
- data/lib/dm-validations/validators/primitive_validator.rb +58 -0
- data/lib/dm-validations/validators/required_field_validator.rb +83 -0
- data/lib/dm-validations/validators/uniqueness_validator.rb +67 -0
- data/lib/dm-validations/validators/within_validator.rb +74 -0
- data/lib/dm-validations/version.rb +5 -0
- data/spec/fixtures/barcode.rb +40 -0
- data/spec/fixtures/basketball_court.rb +58 -0
- data/spec/fixtures/basketball_player.rb +34 -0
- data/spec/fixtures/beta_tester_account.rb +33 -0
- data/spec/fixtures/bill_of_landing.rb +47 -0
- data/spec/fixtures/boat_dock.rb +26 -0
- data/spec/fixtures/city.rb +24 -0
- data/spec/fixtures/company.rb +93 -0
- data/spec/fixtures/corporate_world.rb +39 -0
- data/spec/fixtures/country.rb +24 -0
- data/spec/fixtures/ethernet_frame.rb +56 -0
- data/spec/fixtures/event.rb +44 -0
- data/spec/fixtures/g3_concert.rb +57 -0
- data/spec/fixtures/jabberwock.rb +27 -0
- data/spec/fixtures/kayak.rb +28 -0
- data/spec/fixtures/lernean_hydra.rb +39 -0
- data/spec/fixtures/llama_spaceship.rb +15 -0
- data/spec/fixtures/mathematical_function.rb +34 -0
- data/spec/fixtures/memory_object.rb +30 -0
- data/spec/fixtures/mittelschnauzer.rb +39 -0
- data/spec/fixtures/motor_launch.rb +21 -0
- data/spec/fixtures/multibyte.rb +16 -0
- data/spec/fixtures/page.rb +32 -0
- data/spec/fixtures/phone_number.rb +28 -0
- data/spec/fixtures/pirogue.rb +28 -0
- data/spec/fixtures/programming_language.rb +83 -0
- data/spec/fixtures/reservation.rb +38 -0
- data/spec/fixtures/scm_operation.rb +56 -0
- data/spec/fixtures/sms_message.rb +22 -0
- data/spec/fixtures/udp_packet.rb +49 -0
- data/spec/integration/absent_field_validator/absent_field_validator_spec.rb +90 -0
- data/spec/integration/absent_field_validator/spec_helper.rb +7 -0
- data/spec/integration/acceptance_validator/acceptance_validator_spec.rb +196 -0
- data/spec/integration/acceptance_validator/spec_helper.rb +7 -0
- data/spec/integration/automatic_validation/custom_messages_for_inferred_validation_spec.rb +57 -0
- data/spec/integration/automatic_validation/disabling_inferred_validation_spec.rb +49 -0
- data/spec/integration/automatic_validation/inferred_boolean_properties_validation_spec.rb +100 -0
- data/spec/integration/automatic_validation/inferred_float_property_validation_spec.rb +45 -0
- data/spec/integration/automatic_validation/inferred_format_validation_spec.rb +35 -0
- data/spec/integration/automatic_validation/inferred_integer_properties_validation_spec.rb +70 -0
- data/spec/integration/automatic_validation/inferred_length_validation_spec.rb +142 -0
- data/spec/integration/automatic_validation/inferred_presence_validation_spec.rb +45 -0
- data/spec/integration/automatic_validation/inferred_primitive_validation_spec.rb +22 -0
- data/spec/integration/automatic_validation/inferred_uniqueness_validation_spec.rb +52 -0
- data/spec/integration/automatic_validation/inferred_within_validation_spec.rb +39 -0
- data/spec/integration/automatic_validation/spec_helper.rb +57 -0
- data/spec/integration/block_validator/block_validator_spec.rb +32 -0
- data/spec/integration/block_validator/spec_helper.rb +5 -0
- data/spec/integration/conditional_validation/if_condition_spec.rb +63 -0
- data/spec/integration/conditional_validation/spec_helper.rb +5 -0
- data/spec/integration/confirmation_validator/confirmation_validator_spec.rb +76 -0
- data/spec/integration/confirmation_validator/spec_helper.rb +5 -0
- data/spec/integration/datamapper_models/association_validation_spec.rb +29 -0
- data/spec/integration/datamapper_models/inheritance_spec.rb +82 -0
- data/spec/integration/dirty_attributes/dirty_attributes_spec.rb +13 -0
- data/spec/integration/duplicated_validations/duplicated_validations_spec.rb +24 -0
- data/spec/integration/duplicated_validations/spec_helper.rb +5 -0
- data/spec/integration/format_validator/email_format_validator_spec.rb +139 -0
- data/spec/integration/format_validator/format_validator_spec.rb +64 -0
- data/spec/integration/format_validator/regexp_validator_spec.rb +33 -0
- data/spec/integration/format_validator/spec_helper.rb +5 -0
- data/spec/integration/format_validator/url_format_validator_spec.rb +93 -0
- data/spec/integration/length_validator/default_value_spec.rb +14 -0
- data/spec/integration/length_validator/equality_spec.rb +87 -0
- data/spec/integration/length_validator/error_message_spec.rb +22 -0
- data/spec/integration/length_validator/maximum_spec.rb +49 -0
- data/spec/integration/length_validator/minimum_spec.rb +54 -0
- data/spec/integration/length_validator/range_spec.rb +87 -0
- data/spec/integration/length_validator/spec_helper.rb +7 -0
- data/spec/integration/method_validator/method_validator_spec.rb +241 -0
- data/spec/integration/method_validator/spec_helper.rb +5 -0
- data/spec/integration/numeric_validator/equality_with_float_type_spec.rb +65 -0
- data/spec/integration/numeric_validator/equality_with_integer_type_spec.rb +41 -0
- data/spec/integration/numeric_validator/float_type_spec.rb +90 -0
- data/spec/integration/numeric_validator/gt_with_float_type_spec.rb +37 -0
- data/spec/integration/numeric_validator/gte_with_float_type_spec.rb +37 -0
- data/spec/integration/numeric_validator/integer_only_true_spec.rb +91 -0
- data/spec/integration/numeric_validator/integer_type_spec.rb +86 -0
- data/spec/integration/numeric_validator/lt_with_float_type_spec.rb +37 -0
- data/spec/integration/numeric_validator/lte_with_float_type_spec.rb +37 -0
- data/spec/integration/numeric_validator/spec_helper.rb +5 -0
- data/spec/integration/primitive_validator/primitive_validator_spec.rb +92 -0
- data/spec/integration/primitive_validator/spec_helper.rb +5 -0
- data/spec/integration/pure_ruby_objects/plain_old_ruby_object_validation_spec.rb +118 -0
- data/spec/integration/required_field_validator/association_spec.rb +72 -0
- data/spec/integration/required_field_validator/boolean_type_value_spec.rb +155 -0
- data/spec/integration/required_field_validator/date_type_value_spec.rb +127 -0
- data/spec/integration/required_field_validator/datetime_type_value_spec.rb +127 -0
- data/spec/integration/required_field_validator/float_type_value_spec.rb +131 -0
- data/spec/integration/required_field_validator/integer_type_value_spec.rb +99 -0
- data/spec/integration/required_field_validator/plain_old_ruby_object_spec.rb +35 -0
- data/spec/integration/required_field_validator/shared_examples.rb +26 -0
- data/spec/integration/required_field_validator/spec_helper.rb +7 -0
- data/spec/integration/required_field_validator/string_type_value_spec.rb +167 -0
- data/spec/integration/required_field_validator/text_type_value_spec.rb +49 -0
- data/spec/integration/shared/default_validation_context.rb +13 -0
- data/spec/integration/shared/valid_and_invalid_model.rb +35 -0
- data/spec/integration/uniqueness_validator/spec_helper.rb +5 -0
- data/spec/integration/uniqueness_validator/uniqueness_validator_spec.rb +116 -0
- data/spec/integration/within_validator/spec_helper.rb +5 -0
- data/spec/integration/within_validator/within_validator_spec.rb +168 -0
- data/spec/public/resource_spec.rb +105 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/unit/contextual_validators/emptiness_spec.rb +50 -0
- data/spec/unit/contextual_validators/execution_spec.rb +48 -0
- data/spec/unit/contextual_validators/spec_helper.rb +37 -0
- data/spec/unit/generic_validator/equality_operator_spec.rb +26 -0
- data/spec/unit/generic_validator/optional_spec.rb +54 -0
- data/spec/unit/validation_errors/adding_spec.rb +54 -0
- data/spec/unit/validation_errors/emptiness_spec.rb +38 -0
- data/spec/unit/validation_errors/enumerable_spec.rb +32 -0
- data/spec/unit/validation_errors/reading_spec.rb +35 -0
- data/spec/unit/validation_errors/respond_to_spec.rb +15 -0
- data/spec/unit/validators/within_validator_spec.rb +23 -0
- data/tasks/spec.rake +38 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +256 -0
@@ -0,0 +1,184 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module DataMapper
|
3
|
+
module Validations
|
4
|
+
# All validators extend this base class. Validators must:
|
5
|
+
#
|
6
|
+
# * Implement the initialize method to capture its parameters, also
|
7
|
+
# calling super to have this parent class capture the optional,
|
8
|
+
# general :if and :unless parameters.
|
9
|
+
# * Implement the call method, returning true or false. The call method
|
10
|
+
# provides the validation logic.
|
11
|
+
#
|
12
|
+
# @author Guy van den Berg
|
13
|
+
# @since 0.9
|
14
|
+
class GenericValidator
|
15
|
+
|
16
|
+
attr_accessor :if_clause, :unless_clause
|
17
|
+
attr_reader :field_name, :options, :humanized_field_name
|
18
|
+
|
19
|
+
# Construct a validator. Capture the :if and :unless clauses when
|
20
|
+
# present.
|
21
|
+
#
|
22
|
+
# @param [String, Symbol] field
|
23
|
+
# The property specified for validation.
|
24
|
+
#
|
25
|
+
# @option [Symbol, Proc] :if
|
26
|
+
# The name of a method or a Proc to call to determine if the
|
27
|
+
# validation should occur.
|
28
|
+
#
|
29
|
+
# @option [Symbol, Proc] :unless
|
30
|
+
# The name of a method or a Proc to call to determine if the
|
31
|
+
# validation should not occur.
|
32
|
+
#
|
33
|
+
# @note
|
34
|
+
# All additional key/value pairs are passed through to the validator
|
35
|
+
# that is sub-classing this GenericValidator
|
36
|
+
#
|
37
|
+
def initialize(field_name, options = {})
|
38
|
+
@field_name = field_name
|
39
|
+
@options = DataMapper::Ext::Hash.except(options, :if, :unless)
|
40
|
+
@if_clause = options[:if]
|
41
|
+
@unless_clause = options[:unless]
|
42
|
+
@humanized_field_name = DataMapper::Inflector.humanize(@field_name)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Add an error message to a target resource. If the error corresponds
|
46
|
+
# to a specific field of the resource, add it to that field,
|
47
|
+
# otherwise add it as a :general message.
|
48
|
+
#
|
49
|
+
# @param [Object] target
|
50
|
+
# The resource that has the error.
|
51
|
+
#
|
52
|
+
# @param [String] message
|
53
|
+
# The message to add.
|
54
|
+
#
|
55
|
+
# @param [Symbol] field_name
|
56
|
+
# The name of the field that caused the error.
|
57
|
+
#
|
58
|
+
def add_error(target, message, field_name = :general)
|
59
|
+
# TODO: should the field_name for a general message be :default???
|
60
|
+
target.errors.add(field_name, message)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Call the validator. "call" is used so the operation is BoundMethod
|
64
|
+
# and Block compatible. This must be implemented in all concrete
|
65
|
+
# classes.
|
66
|
+
#
|
67
|
+
# @param [Object] target
|
68
|
+
# The resource that the validator must be called against.
|
69
|
+
#
|
70
|
+
# @return [Boolean]
|
71
|
+
# true if valid, otherwise false.
|
72
|
+
#
|
73
|
+
def call(target)
|
74
|
+
raise NotImplementedError, "#{self.class}#call must be implemented"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Determines if this validator should be run against the
|
78
|
+
# target by evaluating the :if and :unless clauses
|
79
|
+
# optionally passed while specifying any validator.
|
80
|
+
#
|
81
|
+
# @param [Object] target
|
82
|
+
# The resource that we check against.
|
83
|
+
#
|
84
|
+
# @return [Boolean]
|
85
|
+
# true if should be run, otherwise false.
|
86
|
+
#
|
87
|
+
# @api private
|
88
|
+
def execute?(target)
|
89
|
+
if unless_clause = self.unless_clause
|
90
|
+
!evaluate_conditional_clause(target, unless_clause)
|
91
|
+
elsif if_clause = self.if_clause
|
92
|
+
evaluate_conditional_clause(target, if_clause)
|
93
|
+
else
|
94
|
+
true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# @api private
|
99
|
+
def evaluate_conditional_clause(target, clause)
|
100
|
+
if clause.kind_of?(Symbol)
|
101
|
+
target.__send__(clause)
|
102
|
+
elsif clause.respond_to?(:call)
|
103
|
+
clause.call(target)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Set the default value for allow_nil and allow_blank
|
108
|
+
#
|
109
|
+
# @param [Boolean] default value
|
110
|
+
#
|
111
|
+
# @api private
|
112
|
+
def set_optional_by_default(default = true)
|
113
|
+
[ :allow_nil, :allow_blank ].each do |key|
|
114
|
+
@options[key] = true unless options.key?(key)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Test the value to see if it is blank or nil, and if it is allowed.
|
119
|
+
# Note that allowing blank without explicitly denying nil allows nil
|
120
|
+
# values, since nil.blank? is true.
|
121
|
+
#
|
122
|
+
# @param [Object] value
|
123
|
+
# The value to test.
|
124
|
+
#
|
125
|
+
# @return [Boolean]
|
126
|
+
# true if blank/nil is allowed, and the value is blank/nil.
|
127
|
+
#
|
128
|
+
# @api private
|
129
|
+
def optional?(value)
|
130
|
+
if value.nil?
|
131
|
+
@options[:allow_nil] ||
|
132
|
+
(@options[:allow_blank] && !@options.has_key?(:allow_nil))
|
133
|
+
elsif DataMapper::Ext.blank?(value)
|
134
|
+
@options[:allow_blank]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns true if validators are equal
|
139
|
+
#
|
140
|
+
# Note that this intentionally do
|
141
|
+
# validate options equality
|
142
|
+
#
|
143
|
+
# even though it is hard to imagine a situation
|
144
|
+
# when multiple validations will be used
|
145
|
+
# on the same field with the same conditions
|
146
|
+
# but different options,
|
147
|
+
# it happens to be the case every once in a while
|
148
|
+
# with inferred validations for strings/text and
|
149
|
+
# explicitly given validations with different option
|
150
|
+
# (usually as Range vs. max limit for inferred validation)
|
151
|
+
#
|
152
|
+
# @api semipublic
|
153
|
+
def ==(other)
|
154
|
+
self.class == other.class &&
|
155
|
+
self.field_name == other.field_name &&
|
156
|
+
self.if_clause == other.if_clause &&
|
157
|
+
self.unless_clause == other.unless_clause &&
|
158
|
+
self.options == other.options
|
159
|
+
end
|
160
|
+
|
161
|
+
def inspect
|
162
|
+
"<##{self.class.name} @field_name='#{@field_name}' @if_clause=#{@if_clause.inspect} @unless_clause=#{@unless_clause.inspect} @options=#{@options.inspect}>"
|
163
|
+
end
|
164
|
+
|
165
|
+
alias_method :to_s, :inspect
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
# Get the corresponding Resource property, if it exists.
|
170
|
+
#
|
171
|
+
# Note: DataMapper validations can be used on non-DataMapper resources.
|
172
|
+
# In such cases, the return value will be nil.
|
173
|
+
#
|
174
|
+
# @api private
|
175
|
+
def get_resource_property(resource, property_name)
|
176
|
+
model = resource.model if resource.respond_to?(:model)
|
177
|
+
repository = resource.repository if model
|
178
|
+
properties = model.properties(repository.name) if model
|
179
|
+
properties[property_name] if properties
|
180
|
+
end
|
181
|
+
|
182
|
+
end # class GenericValidator
|
183
|
+
end # module Validations
|
184
|
+
end # module DataMapper
|
@@ -0,0 +1,249 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validations
|
3
|
+
class LengthValidator < GenericValidator
|
4
|
+
|
5
|
+
# Initialize a length validator
|
6
|
+
#
|
7
|
+
# @param [Symbol] field_name
|
8
|
+
# the name of the field to validate
|
9
|
+
#
|
10
|
+
# @param [Hash] options
|
11
|
+
# the validator options
|
12
|
+
#
|
13
|
+
# @api semipublic
|
14
|
+
def initialize(field_name, options)
|
15
|
+
super
|
16
|
+
|
17
|
+
@equal = options[:is] || options[:equals]
|
18
|
+
@range = options[:within] || options[:in]
|
19
|
+
@min = options[:minimum] || options[:min]
|
20
|
+
@max = options[:maximum] || options[:max]
|
21
|
+
|
22
|
+
if @min && @max
|
23
|
+
@range ||= @min..@max
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Test the resource field for validity
|
28
|
+
#
|
29
|
+
# @example when the resource field is valid
|
30
|
+
# validator.call(valid_resource) # => true
|
31
|
+
#
|
32
|
+
# @example when the resource field is not valid
|
33
|
+
# validator.call(invalid_resource) # => false
|
34
|
+
#
|
35
|
+
#
|
36
|
+
# @param [Resource] target
|
37
|
+
# the Resource to test
|
38
|
+
#
|
39
|
+
# @return [Boolean]
|
40
|
+
# true if the field is valid, false if not
|
41
|
+
#
|
42
|
+
# @api semipublic
|
43
|
+
def call(target)
|
44
|
+
value = target.validation_property_value(field_name)
|
45
|
+
return true if optional?(value)
|
46
|
+
|
47
|
+
return true unless error_message = error_message_for(value)
|
48
|
+
|
49
|
+
add_error(target, error_message, field_name)
|
50
|
+
false
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Return the error messages for the value if it is invalid
|
56
|
+
#
|
57
|
+
# @param [#to_s] value
|
58
|
+
# the value to test
|
59
|
+
#
|
60
|
+
# @return [String, nil]
|
61
|
+
# the error message if invalid, nil if not
|
62
|
+
#
|
63
|
+
# @api private
|
64
|
+
def error_message_for(value)
|
65
|
+
if error_message = send(validation_method, value_length(value.to_s))
|
66
|
+
@options.fetch(:message, error_message)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return the method to validate the value with
|
71
|
+
#
|
72
|
+
# @return [Symbol]
|
73
|
+
# the validation method
|
74
|
+
#
|
75
|
+
# @api private
|
76
|
+
def validation_method
|
77
|
+
@validation_method ||=
|
78
|
+
if @equal then :validate_equals
|
79
|
+
elsif @range then :validate_range
|
80
|
+
elsif @min then :validate_min
|
81
|
+
elsif @max then :validate_max
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Return the length in characters
|
86
|
+
#
|
87
|
+
# @param [#to_str] value
|
88
|
+
# the string to get the number of characters for
|
89
|
+
#
|
90
|
+
# @return [Integer]
|
91
|
+
# the number of characters in the string
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
def value_length(value)
|
95
|
+
value.to_str.length
|
96
|
+
end
|
97
|
+
|
98
|
+
if RUBY_VERSION < '1.9'
|
99
|
+
def value_length(value)
|
100
|
+
value.to_str.scan(/./u).size
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Validate the value length is equal to the expected length
|
105
|
+
#
|
106
|
+
# @param [Integer] length
|
107
|
+
# the value length
|
108
|
+
#
|
109
|
+
# @return [String, nil]
|
110
|
+
# the error message if invalid, nil if not
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
def validate_equals(length)
|
114
|
+
return if length == @equal
|
115
|
+
|
116
|
+
ValidationErrors.default_error_message(
|
117
|
+
:wrong_length,
|
118
|
+
humanized_field_name,
|
119
|
+
@equal
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Validate the value length is within expected range
|
124
|
+
#
|
125
|
+
# @param [Integer] length
|
126
|
+
# the value length
|
127
|
+
#
|
128
|
+
# @return [String, nil]
|
129
|
+
# the error message if invalid, nil if not
|
130
|
+
#
|
131
|
+
# @api private
|
132
|
+
def validate_range(length)
|
133
|
+
return if @range.include?(length)
|
134
|
+
|
135
|
+
ValidationErrors.default_error_message(
|
136
|
+
:length_between,
|
137
|
+
humanized_field_name,
|
138
|
+
@range.min,
|
139
|
+
@range.max
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Validate the minimum expected value length
|
144
|
+
#
|
145
|
+
# @param [Integer] length
|
146
|
+
# the value length
|
147
|
+
#
|
148
|
+
# @return [String, nil]
|
149
|
+
# the error message if invalid, nil if not
|
150
|
+
#
|
151
|
+
# @api private
|
152
|
+
def validate_min(length)
|
153
|
+
return if length >= @min
|
154
|
+
|
155
|
+
ValidationErrors.default_error_message(
|
156
|
+
:too_short,
|
157
|
+
humanized_field_name,
|
158
|
+
@min
|
159
|
+
)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Validate the maximum expected value length
|
163
|
+
#
|
164
|
+
# @param [Integer] length
|
165
|
+
# the value length
|
166
|
+
#
|
167
|
+
# @return [String, nil]
|
168
|
+
# the error message if invalid, nil if not
|
169
|
+
#
|
170
|
+
# @api private
|
171
|
+
def validate_max(length)
|
172
|
+
return if length <= @max
|
173
|
+
|
174
|
+
ValidationErrors.default_error_message(
|
175
|
+
:too_long,
|
176
|
+
humanized_field_name,
|
177
|
+
@max
|
178
|
+
)
|
179
|
+
end
|
180
|
+
|
181
|
+
end # class LengthValidator
|
182
|
+
|
183
|
+
module ValidatesLength
|
184
|
+
extend Deprecate
|
185
|
+
|
186
|
+
# Validates that the length of the attribute is equal to, less than,
|
187
|
+
# greater than or within a certain range (depending upon the options
|
188
|
+
# you specify).
|
189
|
+
#
|
190
|
+
# @option [Boolean] :allow_nil (true)
|
191
|
+
# true or false.
|
192
|
+
#
|
193
|
+
# @option [Boolean] :allow_blank (true)
|
194
|
+
# true or false.
|
195
|
+
#
|
196
|
+
# @option [Boolean] :minimum
|
197
|
+
# Ensures that the attribute's length is greater than or equal to
|
198
|
+
# the supplied value.
|
199
|
+
#
|
200
|
+
# @option [Boolean] :min
|
201
|
+
# Alias for :minimum.
|
202
|
+
#
|
203
|
+
# @option [Boolean] :maximum
|
204
|
+
# Ensures the attribute's length is less than or equal to the
|
205
|
+
# supplied value.
|
206
|
+
#
|
207
|
+
# @option [Boolean] :max
|
208
|
+
# Alias for :maximum.
|
209
|
+
#
|
210
|
+
# @option [Boolean] :equals
|
211
|
+
# Ensures the attribute's length is equal to the supplied value.
|
212
|
+
#
|
213
|
+
# @option [Boolean] :is
|
214
|
+
# Alias for :equals.
|
215
|
+
#
|
216
|
+
# @option [Range] :in
|
217
|
+
# Given a Range, ensures that the attributes length is include?'ed
|
218
|
+
# in the Range.
|
219
|
+
#
|
220
|
+
# @option [Range] :within
|
221
|
+
# Alias for :in.
|
222
|
+
#
|
223
|
+
# @example Usage
|
224
|
+
# require 'dm-validations'
|
225
|
+
#
|
226
|
+
# class Page
|
227
|
+
# include DataMapper::Resource
|
228
|
+
#
|
229
|
+
# property high, Integer
|
230
|
+
# property low, Integer
|
231
|
+
# property just_right, Integer
|
232
|
+
#
|
233
|
+
# validates_length_of :high, :min => 100000000000
|
234
|
+
# validates_length_of :low, :equals => 0
|
235
|
+
# validates_length_of :just_right, :within => 1..10
|
236
|
+
#
|
237
|
+
# # a call to valid? will return false unless:
|
238
|
+
# # high is greater than or equal to 100000000000
|
239
|
+
# # low is equal to 0
|
240
|
+
# # just_right is between 1 and 10 (inclusive of both 1 and 10)
|
241
|
+
#
|
242
|
+
def validates_length_of(*fields)
|
243
|
+
validators.add(LengthValidator, *fields)
|
244
|
+
end
|
245
|
+
|
246
|
+
deprecate :validates_length, :validates_length_of
|
247
|
+
end # module ValidatesLength
|
248
|
+
end # module Validations
|
249
|
+
end # module DataMapper
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validations
|
3
|
+
# @author Guy van den Berg
|
4
|
+
# @since 0.9
|
5
|
+
class MethodValidator < GenericValidator
|
6
|
+
|
7
|
+
def initialize(field_name, options={})
|
8
|
+
super
|
9
|
+
@options[:method] = @field_name unless @options.key?(:method)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(target)
|
13
|
+
result, message = target.__send__(@options[:method])
|
14
|
+
add_error(target, message, field_name) unless result
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(other)
|
19
|
+
@options[:method] == other.instance_variable_get(:@options)[:method] && super
|
20
|
+
end
|
21
|
+
|
22
|
+
end # class MethodValidator
|
23
|
+
|
24
|
+
module ValidatesWithMethod
|
25
|
+
# Validate using method called on validated object. The method must
|
26
|
+
# to return either true, or a pair of [false, error message string],
|
27
|
+
# and is specified as a symbol passed with :method option.
|
28
|
+
#
|
29
|
+
# This validator does support multiple fields being specified at a
|
30
|
+
# time, but we encourage you to use it with one property/method at a
|
31
|
+
# time.
|
32
|
+
#
|
33
|
+
# Real world experience shows that method validation is often useful
|
34
|
+
# when attribute needs to be virtual and not a property name.
|
35
|
+
#
|
36
|
+
# @example Usage
|
37
|
+
# require 'dm-validations'
|
38
|
+
#
|
39
|
+
# class Page
|
40
|
+
# include DataMapper::Resource
|
41
|
+
#
|
42
|
+
# property :zip_code, String
|
43
|
+
#
|
44
|
+
# validates_with_method :zip_code,
|
45
|
+
# :method => :in_the_right_location?
|
46
|
+
#
|
47
|
+
# def in_the_right_location?
|
48
|
+
# if @zip_code == "94301"
|
49
|
+
# return true
|
50
|
+
# else
|
51
|
+
# return [false, "You're in the wrong zip code"]
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# # A call to valid? will return false and
|
56
|
+
# # populate the object's errors with "You're in the
|
57
|
+
# # wrong zip code" unless zip_code == "94301"
|
58
|
+
# end
|
59
|
+
def validates_with_method(*fields)
|
60
|
+
validators.add(MethodValidator, *fields)
|
61
|
+
end
|
62
|
+
end # module ValidatesWithMethod
|
63
|
+
end # module Validations
|
64
|
+
end # module DataMapper
|