ardm-validations 1.2.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.
- 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
|