dm-validations 0.9.11 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{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
|