dm-validations 0.9.11 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{History.txt → History.rdoc} +10 -3
- data/LICENSE +1 -0
- data/Manifest.txt +103 -33
- data/README.rdoc +172 -0
- data/Rakefile +4 -5
- data/lib/dm-validations.rb +73 -75
- data/lib/dm-validations/auto_validate.rb +98 -56
- data/lib/dm-validations/contextual_validators.rb +37 -14
- data/lib/dm-validations/exceptions.rb +3 -0
- data/lib/dm-validations/formats/url.rb +3 -1
- data/lib/dm-validations/support/context.rb +54 -0
- data/lib/dm-validations/validation_errors.rb +51 -27
- data/lib/dm-validations/{absent_field_validator.rb → validators/absent_field_validator.rb} +2 -8
- data/lib/dm-validations/{acceptance_validator.rb → validators/acceptance_validator.rb} +7 -7
- data/lib/dm-validations/{block_validator.rb → validators/block_validator.rb} +0 -0
- data/lib/dm-validations/{confirmation_validator.rb → validators/confirmation_validator.rb} +7 -7
- data/lib/dm-validations/{format_validator.rb → validators/format_validator.rb} +10 -16
- data/lib/dm-validations/{generic_validator.rb → validators/generic_validator.rb} +28 -6
- data/lib/dm-validations/validators/length_validator.rb +214 -0
- data/lib/dm-validations/validators/method_validator.rb +68 -0
- data/lib/dm-validations/validators/numeric_validator.rb +171 -0
- data/lib/dm-validations/{primitive_validator.rb → validators/primitive_validator.rb} +2 -7
- data/lib/dm-validations/{required_field_validator.rb → validators/required_field_validator.rb} +0 -6
- data/lib/dm-validations/{uniqueness_validator.rb → validators/uniqueness_validator.rb} +9 -20
- data/lib/dm-validations/{within_validator.rb → validators/within_validator.rb} +4 -4
- data/lib/dm-validations/version.rb +1 -1
- data/spec/fixtures/barcode.rb +32 -0
- data/spec/fixtures/basketball_court.rb +58 -0
- data/spec/fixtures/basketball_player.rb +37 -0
- data/spec/fixtures/beta_tester_account.rb +33 -0
- data/spec/fixtures/bill_of_landing.rb +42 -0
- data/spec/fixtures/boat_dock.rb +26 -0
- data/spec/fixtures/city.rb +25 -0
- data/spec/fixtures/company.rb +95 -0
- data/spec/fixtures/corporate_world.rb +47 -0
- data/spec/fixtures/country.rb +25 -0
- data/spec/fixtures/currency.rb +42 -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/mathematical_function.rb +34 -0
- data/spec/fixtures/memory_object.rb +30 -0
- data/spec/fixtures/mittelschnauzer.rb +35 -0
- data/spec/fixtures/motor_launch.rb +21 -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 +67 -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 +86 -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 +47 -0
- data/spec/integration/automatic_validation/disabling_inferred_validation_spec.rb +41 -0
- data/spec/integration/automatic_validation/inferred_boolean_properties_validation_spec.rb +104 -0
- data/spec/integration/automatic_validation/inferred_float_property_validation_spec.rb +35 -0
- data/spec/integration/automatic_validation/inferred_format_validation_spec.rb +33 -0
- data/spec/integration/automatic_validation/inferred_integer_properties_validation_spec.rb +73 -0
- data/spec/integration/automatic_validation/inferred_length_validation_spec.rb +121 -0
- data/spec/integration/automatic_validation/inferred_presence_validation_spec.rb +41 -0
- data/spec/integration/automatic_validation/inferred_primitive_validation_spec.rb +20 -0
- data/spec/integration/automatic_validation/inferred_within_validation_spec.rb +33 -0
- data/spec/integration/automatic_validation/spec_helper.rb +74 -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 +61 -0
- data/spec/integration/conditional_validation/spec_helper.rb +5 -0
- data/spec/integration/confirmation_validator/confirmation_validator_spec.rb +74 -0
- data/spec/integration/confirmation_validator/spec_helper.rb +5 -0
- data/spec/integration/datamapper_models/association_validation_spec.rb +23 -0
- data/spec/integration/datamapper_models/inheritance_spec.rb +78 -0
- data/spec/integration/duplicated_validations/duplicated_validations_spec.rb +22 -0
- data/spec/integration/duplicated_validations/spec_helper.rb +5 -0
- data/spec/integration/format_validator/email_format_validator_spec.rb +113 -0
- data/spec/integration/format_validator/format_validator_spec.rb +60 -0
- data/spec/integration/format_validator/regexp_validator_spec.rb +29 -0
- data/spec/integration/format_validator/spec_helper.rb +5 -0
- data/spec/integration/format_validator/url_format_validator_spec.rb +63 -0
- data/spec/integration/length_validator/default_value_spec.rb +12 -0
- data/spec/integration/length_validator/equality_spec.rb +79 -0
- data/spec/integration/length_validator/error_message_spec.rb +15 -18
- data/spec/integration/length_validator/maximum_spec.rb +40 -24
- data/spec/integration/length_validator/minimum_spec.rb +32 -21
- data/spec/integration/length_validator/range_spec.rb +50 -60
- data/spec/integration/length_validator/spec_helper.rb +7 -12
- data/spec/integration/method_validator/method_validator_spec.rb +239 -0
- data/spec/integration/method_validator/spec_helper.rb +5 -0
- data/spec/integration/numeric_validator/equality_with_float_type_spec.rb +61 -0
- data/spec/integration/numeric_validator/equality_with_integer_type_spec.rb +37 -0
- data/spec/integration/numeric_validator/float_type_spec.rb +42 -56
- data/spec/integration/numeric_validator/gt_with_float_type_spec.rb +35 -0
- data/spec/integration/numeric_validator/gte_with_float_type_spec.rb +35 -0
- data/spec/integration/numeric_validator/integer_only_true_spec.rb +3 -6
- data/spec/integration/numeric_validator/integer_type_spec.rb +8 -24
- data/spec/integration/numeric_validator/lt_with_float_type_spec.rb +35 -0
- data/spec/integration/numeric_validator/lte_with_float_type_spec.rb +35 -0
- data/spec/integration/numeric_validator/spec_helper.rb +5 -77
- data/spec/integration/primitive_validator/primitive_validator_spec.rb +90 -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 +5 -8
- data/spec/integration/required_field_validator/boolean_type_value_spec.rb +4 -7
- data/spec/integration/required_field_validator/date_type_value_spec.rb +3 -6
- data/spec/integration/required_field_validator/datetime_type_value_spec.rb +3 -6
- data/spec/integration/required_field_validator/float_type_value_spec.rb +3 -6
- data/spec/integration/required_field_validator/integer_type_value_spec.rb +2 -5
- data/spec/integration/required_field_validator/plain_old_ruby_object_spec.rb +5 -8
- data/spec/integration/required_field_validator/shared_examples.rb +1 -1
- data/spec/integration/required_field_validator/spec_helper.rb +6 -67
- data/spec/integration/required_field_validator/string_type_value_spec.rb +2 -5
- data/spec/integration/required_field_validator/text_type_value_spec.rb +2 -5
- data/spec/integration/shared/default_validation_context.rb +13 -0
- data/spec/integration/shared/valid_and_invalid_model.rb +27 -0
- data/spec/integration/uniqueness_validator/spec_helper.rb +5 -0
- data/spec/integration/uniqueness_validator/uniqueness_validator_spec.rb +114 -0
- data/spec/integration/within_validator/spec_helper.rb +5 -0
- data/spec/integration/within_validator/within_validator_spec.rb +164 -0
- data/spec/public/resource_spec.rb +68 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +12 -4
- data/spec/unit/contextual_validators/emptiness_spec.rb +50 -0
- data/spec/unit/contextual_validators/execution_spec.rb +55 -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/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/tasks/install.rb +1 -1
- data/tasks/spec.rb +4 -4
- metadata +118 -55
- data/README.txt +0 -72
- data/lib/dm-validations/custom_validator.rb +0 -72
- data/lib/dm-validations/length_validator.rb +0 -113
- data/lib/dm-validations/method_validator.rb +0 -68
- data/lib/dm-validations/numeric_validator.rb +0 -83
- data/spec/integration/absent_field_validator_spec.rb +0 -36
- data/spec/integration/acceptance_validator_spec.rb +0 -87
- data/spec/integration/auto_validate_spec.rb +0 -342
- data/spec/integration/block_validator_spec.rb +0 -30
- data/spec/integration/confirmation_validator_spec.rb +0 -105
- data/spec/integration/contextual_validators_spec.rb +0 -27
- data/spec/integration/custom_validator_spec.rb +0 -9
- data/spec/integration/format_validator_spec.rb +0 -193
- data/spec/integration/generic_validator_spec.rb +0 -17
- data/spec/integration/length_validator/valid_objects_spec.rb +0 -13
- data/spec/integration/method_validator_spec.rb +0 -58
- data/spec/integration/numeric_validator_spec.rb +0 -253
- data/spec/integration/primitive_validator_spec.rb +0 -30
- data/spec/integration/uniqueness_validator_spec.rb +0 -97
- data/spec/integration/validation_errors_spec.rb +0 -18
- data/spec/integration/validation_spec.rb +0 -404
- data/spec/integration/within_validator_spec.rb +0 -79
@@ -6,16 +6,10 @@ module DataMapper
|
|
6
6
|
# @author Guy van den Berg
|
7
7
|
# @since 0.9
|
8
8
|
class AbsentFieldValidator < GenericValidator
|
9
|
-
|
10
|
-
def initialize(field_name, options={})
|
11
|
-
super
|
12
|
-
@field_name, @options = field_name, options
|
13
|
-
end
|
14
|
-
|
15
9
|
def call(target)
|
16
|
-
return true if target.send(field_name).blank?
|
10
|
+
return true if target.send(self.field_name).blank?
|
17
11
|
|
18
|
-
error_message =
|
12
|
+
error_message = self.options[:message] || ValidationErrors.default_error_message(:absent, field_name)
|
19
13
|
add_error(target, error_message, field_name)
|
20
14
|
|
21
15
|
return false
|
@@ -9,10 +9,10 @@ module DataMapper
|
|
9
9
|
|
10
10
|
def initialize(field_name, options = {})
|
11
11
|
super
|
12
|
-
|
13
|
-
|
14
|
-
@options[:allow_nil] = true unless
|
15
|
-
@options[:accept]
|
12
|
+
|
13
|
+
# ||= true makes value true if it used to be false
|
14
|
+
@options[:allow_nil] = true unless(options.include?(:allow_nil) && [false, nil, "false", "f"].include?(options[:allow_nil]))
|
15
|
+
@options[:accept] ||= ["1", 1, "true", true, "t"]
|
16
16
|
@options[:accept] = Array(@options[:accept])
|
17
17
|
end
|
18
18
|
|
@@ -27,9 +27,9 @@ module DataMapper
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def valid?(target)
|
30
|
-
field_value = target.
|
31
|
-
|
32
|
-
return
|
30
|
+
field_value = target.validation_property_value(field_name)
|
31
|
+
# Allow empty values
|
32
|
+
return true if @options[:allow_nil] && field_value.blank?
|
33
33
|
|
34
34
|
@options[:accept].include?(field_value)
|
35
35
|
end
|
File without changes
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
module DataMapper
|
2
3
|
module Validate
|
3
4
|
|
@@ -9,8 +10,7 @@ module DataMapper
|
|
9
10
|
|
10
11
|
def initialize(field_name, options = {})
|
11
12
|
super
|
12
|
-
@options
|
13
|
-
@field_name, @confirm_field_name = field_name, (options[:confirm] || "#{field_name}_confirmation").to_sym
|
13
|
+
@confirm_field_name = (options[:confirm] || "#{field_name}_confirmation").to_sym
|
14
14
|
@options[:allow_nil] = true unless @options.has_key?(:allow_nil)
|
15
15
|
end
|
16
16
|
|
@@ -26,10 +26,10 @@ module DataMapper
|
|
26
26
|
|
27
27
|
def valid?(target)
|
28
28
|
field_value = target.send(field_name)
|
29
|
-
return true if @options[:allow_nil] && field_value.
|
30
|
-
return false if !@options[:allow_nil] && field_value.
|
29
|
+
return true if @options[:allow_nil] && field_value.blank?
|
30
|
+
return false if !@options[:allow_nil] && field_value.blank?
|
31
31
|
|
32
|
-
if target.
|
32
|
+
if target.model.properties.named?(field_name)
|
33
33
|
return true unless target.attribute_dirty?(field_name)
|
34
34
|
end
|
35
35
|
|
@@ -44,8 +44,8 @@ module DataMapper
|
|
44
44
|
##
|
45
45
|
# Validates that the given attribute is confirmed by another attribute.
|
46
46
|
# A common use case scenario is when you require a user to confirm their
|
47
|
-
#
|
48
|
-
#
|
47
|
+
# password, for which you use both password and password_confirmation
|
48
|
+
# attributes.
|
49
49
|
#
|
50
50
|
# @option :allow_nil<Boolean> true/false (default is true)
|
51
51
|
# @option :confirm<Symbol> the attribute that you want to validate
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#require File.dirname(__FILE__) + '/formats/email'
|
2
2
|
|
3
3
|
require 'pathname'
|
4
|
-
require Pathname(__FILE__).dirname.expand_path + 'formats/email'
|
5
|
-
require Pathname(__FILE__).dirname.expand_path + 'formats/url'
|
4
|
+
require Pathname(__FILE__).dirname.expand_path + ".." + 'formats/email'
|
5
|
+
require Pathname(__FILE__).dirname.expand_path + ".." + 'formats/url'
|
6
6
|
|
7
7
|
module DataMapper
|
8
8
|
module Validate
|
@@ -17,15 +17,15 @@ module DataMapper
|
|
17
17
|
include DataMapper::Validate::Format::Email
|
18
18
|
include DataMapper::Validate::Format::Url
|
19
19
|
|
20
|
-
def initialize(field_name, options = {}
|
21
|
-
super
|
22
|
-
|
23
|
-
@options[:allow_nil] =
|
20
|
+
def initialize(field_name, options = {})
|
21
|
+
super
|
22
|
+
|
23
|
+
@options[:allow_nil] = true unless @options.include?(:allow_nil)
|
24
24
|
end
|
25
25
|
|
26
26
|
def call(target)
|
27
27
|
value = target.validation_property_value(field_name)
|
28
|
-
return true if @options[:allow_nil] && value.
|
28
|
+
return true if @options[:allow_nil] && value.blank?
|
29
29
|
|
30
30
|
validation = @options[:as] || @options[:with]
|
31
31
|
|
@@ -34,7 +34,7 @@ module DataMapper
|
|
34
34
|
|
35
35
|
valid = case validator
|
36
36
|
when Proc then validator.call(value)
|
37
|
-
when Regexp then value =~ validator
|
37
|
+
when Regexp then (value.is_a?(Fixnum) ? value.to_s : value) =~ validator
|
38
38
|
else
|
39
39
|
raise UnknownValidationFormat, "Can't determine how to validate #{target.class}##{field_name} with #{validator.inspect}"
|
40
40
|
end
|
@@ -42,19 +42,13 @@ module DataMapper
|
|
42
42
|
return true if valid
|
43
43
|
|
44
44
|
error_message = @options[:message] || ValidationErrors.default_error_message(:invalid, field_name)
|
45
|
-
|
46
|
-
field = Extlib::Inflection.humanize(field_name)
|
47
|
-
error_message = error_message.call(field, value) if error_message.respond_to?(:call)
|
48
|
-
|
49
|
-
add_error(target, error_message, field_name)
|
45
|
+
add_error(target, error_message.try_call(humanized_field_name, value), field_name)
|
50
46
|
|
51
47
|
false
|
52
48
|
end
|
53
|
-
|
54
|
-
#class UnknownValidationFormat < StandardError; end
|
55
|
-
|
56
49
|
end # class FormatValidator
|
57
50
|
|
51
|
+
|
58
52
|
module ValidatesFormat
|
59
53
|
|
60
54
|
##
|
@@ -15,7 +15,7 @@ module DataMapper
|
|
15
15
|
class GenericValidator
|
16
16
|
|
17
17
|
attr_accessor :if_clause, :unless_clause
|
18
|
-
attr_reader :
|
18
|
+
attr_reader :field_name, :options, :humanized_field_name
|
19
19
|
|
20
20
|
# Construct a validator. Capture the :if and :unless clauses when present.
|
21
21
|
#
|
@@ -28,9 +28,12 @@ module DataMapper
|
|
28
28
|
# All additional key/value pairs are passed through to the validator
|
29
29
|
# that is sub-classing this GenericValidator
|
30
30
|
#
|
31
|
-
def initialize(
|
32
|
-
@if_clause =
|
33
|
-
@unless_clause =
|
31
|
+
def initialize(field_name, options = {})
|
32
|
+
@if_clause = options.delete(:if)
|
33
|
+
@unless_clause = options.delete(:unless)
|
34
|
+
|
35
|
+
@field_name, @options = field_name, options
|
36
|
+
@humanized_field_name = Extlib::Inflection.humanize(@field_name)
|
34
37
|
end
|
35
38
|
|
36
39
|
# Add an error message to a target resource. If the error corresponds to a
|
@@ -83,15 +86,34 @@ module DataMapper
|
|
83
86
|
true
|
84
87
|
end
|
85
88
|
|
89
|
+
# Returns true if validators are equal
|
90
|
+
#
|
91
|
+
# Note that this intentionally do
|
92
|
+
# validate options equality
|
93
|
+
#
|
94
|
+
# even though it is hard to imagine a situation
|
95
|
+
# when multiple validations will be used
|
96
|
+
# on the same field with the same conditions
|
97
|
+
# but different options,
|
98
|
+
# it happens to be the case every once in a while
|
99
|
+
# with inferred validations for strings/text and
|
100
|
+
# explicitly given validations with different option
|
101
|
+
# (usually as Range vs. max limit for inferred validation)
|
102
|
+
#
|
103
|
+
# @semipublic
|
86
104
|
def ==(other)
|
87
105
|
self.class == other.class &&
|
88
106
|
self.field_name == other.field_name &&
|
89
|
-
self.class == other.class &&
|
90
107
|
self.if_clause == other.if_clause &&
|
91
108
|
self.unless_clause == other.unless_clause &&
|
92
109
|
self.instance_variable_get(:@options) == other.instance_variable_get(:@options)
|
93
110
|
end
|
94
111
|
|
112
|
+
def inspect
|
113
|
+
"<##{self.class.name} @field_name='#{@field_name}' @if_clause=#{@if_clause.inspect} @unless_clause=#{@unless_clause.inspect} @options=#{@options.inspect}>"
|
114
|
+
end
|
115
|
+
|
116
|
+
alias to_s inspect
|
95
117
|
end # class GenericValidator
|
96
118
|
end # module Validate
|
97
|
-
end #
|
119
|
+
end # module DataMapper
|
@@ -0,0 +1,214 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validate
|
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
|
+
# @param [Hash] options
|
10
|
+
# the validator options
|
11
|
+
#
|
12
|
+
# @return [undefined]
|
13
|
+
#
|
14
|
+
# @api semipublic
|
15
|
+
def initialize(field_name, options)
|
16
|
+
super
|
17
|
+
|
18
|
+
@equal = options[:is] || options[:equals]
|
19
|
+
@range = options[:within] || options[:in]
|
20
|
+
@min = options[:minimum] || options[:min]
|
21
|
+
@max = options[:maximum] || options[:max]
|
22
|
+
|
23
|
+
if @min && @max
|
24
|
+
@range ||= @min..@max
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Test the resource field for validity
|
29
|
+
#
|
30
|
+
# @example when the resource field is valid
|
31
|
+
# validator.call(valid_resource) # => true
|
32
|
+
#
|
33
|
+
# @example when the resource field is not valid
|
34
|
+
# validator.call(invalid_resource) # => false
|
35
|
+
#
|
36
|
+
#
|
37
|
+
# @param [Resource] target
|
38
|
+
# the Resource to test
|
39
|
+
#
|
40
|
+
# @return [Boolean]
|
41
|
+
# true if the field is valid, false if not
|
42
|
+
#
|
43
|
+
# @api semipublic
|
44
|
+
def call(target)
|
45
|
+
value = target.validation_property_value(field_name)
|
46
|
+
return true if allow_nil? && value.blank?
|
47
|
+
|
48
|
+
return true unless error_message = error_message_for(value)
|
49
|
+
|
50
|
+
add_error(target, error_message, field_name)
|
51
|
+
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# Return if the validation allows nil values
|
58
|
+
#
|
59
|
+
# @return [Boolean]
|
60
|
+
# true if the validation allows nil, false if not
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
def allow_nil?
|
64
|
+
options.fetch(:allow_nil, false)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return the error messages for the value if it is invalid
|
68
|
+
#
|
69
|
+
# @param [#to_s] value
|
70
|
+
# the value to test
|
71
|
+
#
|
72
|
+
# @return [String, nil]
|
73
|
+
# the error message if invalid, nil if not
|
74
|
+
#
|
75
|
+
# @api private
|
76
|
+
def error_message_for(value)
|
77
|
+
if error_message = send(validation_method, value_length(value.to_s))
|
78
|
+
@options.fetch(:message, error_message)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Return the method to validate the value with
|
83
|
+
#
|
84
|
+
# @return [Symbol]
|
85
|
+
# the validation method
|
86
|
+
#
|
87
|
+
# @api private
|
88
|
+
def validation_method
|
89
|
+
@validation_method ||=
|
90
|
+
if @equal then :validate_equals
|
91
|
+
elsif @range then :validate_range
|
92
|
+
elsif @min then :validate_min
|
93
|
+
elsif @max then :validate_max
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Return the length in characters
|
98
|
+
#
|
99
|
+
# @param [#to_str] value
|
100
|
+
# the string to get the number of characters for
|
101
|
+
#
|
102
|
+
# @return [Integer]
|
103
|
+
# the number of characters in the string
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
def value_length(value)
|
107
|
+
value.to_str.split(//).size
|
108
|
+
end
|
109
|
+
|
110
|
+
# Validate the value length is equal to the expected length
|
111
|
+
#
|
112
|
+
# @param [Integer] length
|
113
|
+
# the value length
|
114
|
+
#
|
115
|
+
# @return [String, nil]
|
116
|
+
# the error message if invalid, nil if not
|
117
|
+
#
|
118
|
+
# @api private
|
119
|
+
def validate_equals(length)
|
120
|
+
return if length == @equal
|
121
|
+
ValidationErrors.default_error_message(:wrong_length, humanized_field_name, @equal)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Validate the value length is within expected range
|
125
|
+
#
|
126
|
+
# @param [Integer] length
|
127
|
+
# the value length
|
128
|
+
#
|
129
|
+
# @return [String, nil]
|
130
|
+
# the error message if invalid, nil if not
|
131
|
+
#
|
132
|
+
# @api private
|
133
|
+
def validate_range(length)
|
134
|
+
return if @range.include?(length)
|
135
|
+
ValidationErrors.default_error_message(:length_between, humanized_field_name, @range.min, @range.max)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Validate the minimum expected value length
|
139
|
+
#
|
140
|
+
# @param [Integer] length
|
141
|
+
# the value length
|
142
|
+
#
|
143
|
+
# @return [String, nil]
|
144
|
+
# the error message if invalid, nil if not
|
145
|
+
#
|
146
|
+
# @api private
|
147
|
+
def validate_min(length)
|
148
|
+
return if length >= @min
|
149
|
+
ValidationErrors.default_error_message(:too_short, humanized_field_name, @min)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Validate the maximum expected value length
|
153
|
+
#
|
154
|
+
# @param [Integer] length
|
155
|
+
# the value length
|
156
|
+
#
|
157
|
+
# @return [String, nil]
|
158
|
+
# the error message if invalid, nil if not
|
159
|
+
#
|
160
|
+
# @api private
|
161
|
+
def validate_max(length)
|
162
|
+
return if length <= @max
|
163
|
+
ValidationErrors.default_error_message(:too_long, humanized_field_name, @max)
|
164
|
+
end
|
165
|
+
|
166
|
+
end # class LengthValidator
|
167
|
+
|
168
|
+
module ValidatesLength
|
169
|
+
|
170
|
+
# Validates that the length of the attribute is equal to, less than,
|
171
|
+
# greater than or within a certain range (depending upon the options
|
172
|
+
# you specify).
|
173
|
+
#
|
174
|
+
# @option :allow_nil<Boolean> true/false (default is true)
|
175
|
+
# @option :minimum ensures that the attribute's length is greater than
|
176
|
+
# or equal to the supplied value
|
177
|
+
# @option :min alias for :minimum
|
178
|
+
# @option :maximum ensures the attribute's length is less than or equal
|
179
|
+
# to the supplied value
|
180
|
+
# @option :max alias for :maximum
|
181
|
+
# @option :equals ensures the attribute's length is equal to the
|
182
|
+
# supplied value
|
183
|
+
# @option :is alias for :equals
|
184
|
+
# @option :in<Range> given a Range, ensures that the attributes length is
|
185
|
+
# include?'ed in the Range
|
186
|
+
# @option :within<Range> alias for :in
|
187
|
+
#
|
188
|
+
# @example [Usage]
|
189
|
+
# require 'dm-validations'
|
190
|
+
#
|
191
|
+
# class Page
|
192
|
+
# include DataMapper::Resource
|
193
|
+
#
|
194
|
+
# property high, Integer
|
195
|
+
# property low, Integer
|
196
|
+
# property just_right, Integer
|
197
|
+
#
|
198
|
+
# validates_length :high, :min => 100000000000
|
199
|
+
# validates_length :low, :equals => 0
|
200
|
+
# validates_length :just_right, :within => 1..10
|
201
|
+
#
|
202
|
+
# # a call to valid? will return false unless:
|
203
|
+
# # high is greater than or equal to 100000000000
|
204
|
+
# # low is equal to 0
|
205
|
+
# # just_right is between 1 and 10 (inclusive of both 1 and 10)
|
206
|
+
#
|
207
|
+
def validates_length(*fields)
|
208
|
+
opts = opts_from_validator_args(fields)
|
209
|
+
add_validator_to_context(opts, fields, DataMapper::Validate::LengthValidator)
|
210
|
+
end
|
211
|
+
|
212
|
+
end # module ValidatesLength
|
213
|
+
end # module Validate
|
214
|
+
end # module DataMapper
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validate
|
3
|
+
|
4
|
+
##
|
5
|
+
#
|
6
|
+
# @author Guy van den Berg
|
7
|
+
# @since 0.9
|
8
|
+
class MethodValidator < GenericValidator
|
9
|
+
|
10
|
+
def initialize(field_name, options={})
|
11
|
+
super
|
12
|
+
@options[:method] = @field_name unless @options.has_key?(:method)
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(target)
|
16
|
+
result, message = target.send(@options[:method])
|
17
|
+
add_error(target, message, field_name) unless result
|
18
|
+
result
|
19
|
+
end
|
20
|
+
|
21
|
+
def ==(other)
|
22
|
+
@options[:method] == other.instance_variable_get(:@options)[:method] && super
|
23
|
+
end
|
24
|
+
end # class MethodValidator
|
25
|
+
|
26
|
+
module ValidatesWithMethod
|
27
|
+
|
28
|
+
##
|
29
|
+
# Validate using method called on validated object. The method must to return
|
30
|
+
# either true, or a pair of [false, error message string], and is specified
|
31
|
+
# as a symbol passed with :method option.
|
32
|
+
#
|
33
|
+
# This validator does support multiple fields being specified at a time,
|
34
|
+
# but we encourage you to use it with one property/method at a time.
|
35
|
+
#
|
36
|
+
# Real world experience shows that method validation is often useful when
|
37
|
+
# attribute needs to be virtual and not a property name.
|
38
|
+
#
|
39
|
+
# @example [Usage]
|
40
|
+
# require 'dm-validations'
|
41
|
+
#
|
42
|
+
# class Page
|
43
|
+
# include DataMapper::Resource
|
44
|
+
#
|
45
|
+
# property :zip_code, String
|
46
|
+
#
|
47
|
+
# validates_with_method :zip_code, :method => :in_the_right_location?
|
48
|
+
#
|
49
|
+
# def in_the_right_location?
|
50
|
+
# if @zip_code == "94301"
|
51
|
+
# return true
|
52
|
+
# else
|
53
|
+
# return [false, "You're in the wrong zip code"]
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# # A call to valid? will return false and
|
58
|
+
# # populate the object's errors with "You're in the
|
59
|
+
# # wrong zip code" unless zip_code == "94301"
|
60
|
+
# end
|
61
|
+
def validates_with_method(*fields)
|
62
|
+
opts = opts_from_validator_args(fields)
|
63
|
+
add_validator_to_context(opts, fields, DataMapper::Validate::MethodValidator)
|
64
|
+
end
|
65
|
+
|
66
|
+
end # module ValidatesWithMethod
|
67
|
+
end # module Validate
|
68
|
+
end # module DataMapper
|