ardm-validations 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +51 -0
  5. data/LICENSE +21 -0
  6. data/README.rdoc +122 -0
  7. data/Rakefile +4 -0
  8. data/ardm-validations.gemspec +28 -0
  9. data/lib/ardm-validations.rb +1 -0
  10. data/lib/dm-validations.rb +169 -0
  11. data/lib/dm-validations/auto_validate.rb +252 -0
  12. data/lib/dm-validations/context.rb +66 -0
  13. data/lib/dm-validations/contextual_validators.rb +220 -0
  14. data/lib/dm-validations/exceptions.rb +5 -0
  15. data/lib/dm-validations/formats/email.rb +65 -0
  16. data/lib/dm-validations/formats/url.rb +27 -0
  17. data/lib/dm-validations/support/object.rb +18 -0
  18. data/lib/dm-validations/support/ordered_hash.rb +434 -0
  19. data/lib/dm-validations/validation_errors.rb +137 -0
  20. data/lib/dm-validations/validators/absent_field_validator.rb +58 -0
  21. data/lib/dm-validations/validators/acceptance_validator.rb +79 -0
  22. data/lib/dm-validations/validators/block_validator.rb +61 -0
  23. data/lib/dm-validations/validators/confirmation_validator.rb +92 -0
  24. data/lib/dm-validations/validators/format_validator.rb +124 -0
  25. data/lib/dm-validations/validators/generic_validator.rb +184 -0
  26. data/lib/dm-validations/validators/length_validator.rb +249 -0
  27. data/lib/dm-validations/validators/method_validator.rb +64 -0
  28. data/lib/dm-validations/validators/numeric_validator.rb +182 -0
  29. data/lib/dm-validations/validators/primitive_validator.rb +58 -0
  30. data/lib/dm-validations/validators/required_field_validator.rb +83 -0
  31. data/lib/dm-validations/validators/uniqueness_validator.rb +67 -0
  32. data/lib/dm-validations/validators/within_validator.rb +74 -0
  33. data/lib/dm-validations/version.rb +5 -0
  34. data/spec/fixtures/barcode.rb +40 -0
  35. data/spec/fixtures/basketball_court.rb +58 -0
  36. data/spec/fixtures/basketball_player.rb +34 -0
  37. data/spec/fixtures/beta_tester_account.rb +33 -0
  38. data/spec/fixtures/bill_of_landing.rb +47 -0
  39. data/spec/fixtures/boat_dock.rb +26 -0
  40. data/spec/fixtures/city.rb +24 -0
  41. data/spec/fixtures/company.rb +93 -0
  42. data/spec/fixtures/corporate_world.rb +39 -0
  43. data/spec/fixtures/country.rb +24 -0
  44. data/spec/fixtures/ethernet_frame.rb +56 -0
  45. data/spec/fixtures/event.rb +44 -0
  46. data/spec/fixtures/g3_concert.rb +57 -0
  47. data/spec/fixtures/jabberwock.rb +27 -0
  48. data/spec/fixtures/kayak.rb +28 -0
  49. data/spec/fixtures/lernean_hydra.rb +39 -0
  50. data/spec/fixtures/llama_spaceship.rb +15 -0
  51. data/spec/fixtures/mathematical_function.rb +34 -0
  52. data/spec/fixtures/memory_object.rb +30 -0
  53. data/spec/fixtures/mittelschnauzer.rb +39 -0
  54. data/spec/fixtures/motor_launch.rb +21 -0
  55. data/spec/fixtures/multibyte.rb +16 -0
  56. data/spec/fixtures/page.rb +32 -0
  57. data/spec/fixtures/phone_number.rb +28 -0
  58. data/spec/fixtures/pirogue.rb +28 -0
  59. data/spec/fixtures/programming_language.rb +83 -0
  60. data/spec/fixtures/reservation.rb +38 -0
  61. data/spec/fixtures/scm_operation.rb +56 -0
  62. data/spec/fixtures/sms_message.rb +22 -0
  63. data/spec/fixtures/udp_packet.rb +49 -0
  64. data/spec/integration/absent_field_validator/absent_field_validator_spec.rb +90 -0
  65. data/spec/integration/absent_field_validator/spec_helper.rb +7 -0
  66. data/spec/integration/acceptance_validator/acceptance_validator_spec.rb +196 -0
  67. data/spec/integration/acceptance_validator/spec_helper.rb +7 -0
  68. data/spec/integration/automatic_validation/custom_messages_for_inferred_validation_spec.rb +57 -0
  69. data/spec/integration/automatic_validation/disabling_inferred_validation_spec.rb +49 -0
  70. data/spec/integration/automatic_validation/inferred_boolean_properties_validation_spec.rb +100 -0
  71. data/spec/integration/automatic_validation/inferred_float_property_validation_spec.rb +45 -0
  72. data/spec/integration/automatic_validation/inferred_format_validation_spec.rb +35 -0
  73. data/spec/integration/automatic_validation/inferred_integer_properties_validation_spec.rb +70 -0
  74. data/spec/integration/automatic_validation/inferred_length_validation_spec.rb +142 -0
  75. data/spec/integration/automatic_validation/inferred_presence_validation_spec.rb +45 -0
  76. data/spec/integration/automatic_validation/inferred_primitive_validation_spec.rb +22 -0
  77. data/spec/integration/automatic_validation/inferred_uniqueness_validation_spec.rb +52 -0
  78. data/spec/integration/automatic_validation/inferred_within_validation_spec.rb +39 -0
  79. data/spec/integration/automatic_validation/spec_helper.rb +57 -0
  80. data/spec/integration/block_validator/block_validator_spec.rb +32 -0
  81. data/spec/integration/block_validator/spec_helper.rb +5 -0
  82. data/spec/integration/conditional_validation/if_condition_spec.rb +63 -0
  83. data/spec/integration/conditional_validation/spec_helper.rb +5 -0
  84. data/spec/integration/confirmation_validator/confirmation_validator_spec.rb +76 -0
  85. data/spec/integration/confirmation_validator/spec_helper.rb +5 -0
  86. data/spec/integration/datamapper_models/association_validation_spec.rb +29 -0
  87. data/spec/integration/datamapper_models/inheritance_spec.rb +82 -0
  88. data/spec/integration/dirty_attributes/dirty_attributes_spec.rb +13 -0
  89. data/spec/integration/duplicated_validations/duplicated_validations_spec.rb +24 -0
  90. data/spec/integration/duplicated_validations/spec_helper.rb +5 -0
  91. data/spec/integration/format_validator/email_format_validator_spec.rb +139 -0
  92. data/spec/integration/format_validator/format_validator_spec.rb +64 -0
  93. data/spec/integration/format_validator/regexp_validator_spec.rb +33 -0
  94. data/spec/integration/format_validator/spec_helper.rb +5 -0
  95. data/spec/integration/format_validator/url_format_validator_spec.rb +93 -0
  96. data/spec/integration/length_validator/default_value_spec.rb +14 -0
  97. data/spec/integration/length_validator/equality_spec.rb +87 -0
  98. data/spec/integration/length_validator/error_message_spec.rb +22 -0
  99. data/spec/integration/length_validator/maximum_spec.rb +49 -0
  100. data/spec/integration/length_validator/minimum_spec.rb +54 -0
  101. data/spec/integration/length_validator/range_spec.rb +87 -0
  102. data/spec/integration/length_validator/spec_helper.rb +7 -0
  103. data/spec/integration/method_validator/method_validator_spec.rb +241 -0
  104. data/spec/integration/method_validator/spec_helper.rb +5 -0
  105. data/spec/integration/numeric_validator/equality_with_float_type_spec.rb +65 -0
  106. data/spec/integration/numeric_validator/equality_with_integer_type_spec.rb +41 -0
  107. data/spec/integration/numeric_validator/float_type_spec.rb +90 -0
  108. data/spec/integration/numeric_validator/gt_with_float_type_spec.rb +37 -0
  109. data/spec/integration/numeric_validator/gte_with_float_type_spec.rb +37 -0
  110. data/spec/integration/numeric_validator/integer_only_true_spec.rb +91 -0
  111. data/spec/integration/numeric_validator/integer_type_spec.rb +86 -0
  112. data/spec/integration/numeric_validator/lt_with_float_type_spec.rb +37 -0
  113. data/spec/integration/numeric_validator/lte_with_float_type_spec.rb +37 -0
  114. data/spec/integration/numeric_validator/spec_helper.rb +5 -0
  115. data/spec/integration/primitive_validator/primitive_validator_spec.rb +92 -0
  116. data/spec/integration/primitive_validator/spec_helper.rb +5 -0
  117. data/spec/integration/pure_ruby_objects/plain_old_ruby_object_validation_spec.rb +118 -0
  118. data/spec/integration/required_field_validator/association_spec.rb +72 -0
  119. data/spec/integration/required_field_validator/boolean_type_value_spec.rb +155 -0
  120. data/spec/integration/required_field_validator/date_type_value_spec.rb +127 -0
  121. data/spec/integration/required_field_validator/datetime_type_value_spec.rb +127 -0
  122. data/spec/integration/required_field_validator/float_type_value_spec.rb +131 -0
  123. data/spec/integration/required_field_validator/integer_type_value_spec.rb +99 -0
  124. data/spec/integration/required_field_validator/plain_old_ruby_object_spec.rb +35 -0
  125. data/spec/integration/required_field_validator/shared_examples.rb +26 -0
  126. data/spec/integration/required_field_validator/spec_helper.rb +7 -0
  127. data/spec/integration/required_field_validator/string_type_value_spec.rb +167 -0
  128. data/spec/integration/required_field_validator/text_type_value_spec.rb +49 -0
  129. data/spec/integration/shared/default_validation_context.rb +13 -0
  130. data/spec/integration/shared/valid_and_invalid_model.rb +35 -0
  131. data/spec/integration/uniqueness_validator/spec_helper.rb +5 -0
  132. data/spec/integration/uniqueness_validator/uniqueness_validator_spec.rb +116 -0
  133. data/spec/integration/within_validator/spec_helper.rb +5 -0
  134. data/spec/integration/within_validator/within_validator_spec.rb +168 -0
  135. data/spec/public/resource_spec.rb +105 -0
  136. data/spec/rcov.opts +6 -0
  137. data/spec/spec.opts +4 -0
  138. data/spec/spec_helper.rb +29 -0
  139. data/spec/unit/contextual_validators/emptiness_spec.rb +50 -0
  140. data/spec/unit/contextual_validators/execution_spec.rb +48 -0
  141. data/spec/unit/contextual_validators/spec_helper.rb +37 -0
  142. data/spec/unit/generic_validator/equality_operator_spec.rb +26 -0
  143. data/spec/unit/generic_validator/optional_spec.rb +54 -0
  144. data/spec/unit/validation_errors/adding_spec.rb +54 -0
  145. data/spec/unit/validation_errors/emptiness_spec.rb +38 -0
  146. data/spec/unit/validation_errors/enumerable_spec.rb +32 -0
  147. data/spec/unit/validation_errors/reading_spec.rb +35 -0
  148. data/spec/unit/validation_errors/respond_to_spec.rb +15 -0
  149. data/spec/unit/validators/within_validator_spec.rb +23 -0
  150. data/tasks/spec.rake +38 -0
  151. data/tasks/yard.rake +9 -0
  152. data/tasks/yardstick.rake +19 -0
  153. metadata +256 -0
@@ -0,0 +1,137 @@
1
+ module DataMapper
2
+ module Validations
3
+ #
4
+ # @author Guy van den Berg
5
+ # @since 0.9
6
+ class ValidationErrors
7
+
8
+ include Enumerable
9
+
10
+ @@default_error_messages = {
11
+ :absent => '%s must be absent',
12
+ :inclusion => '%s must be one of %s',
13
+ :invalid => '%s has an invalid format',
14
+ :confirmation => '%s does not match the confirmation',
15
+ :accepted => '%s is not accepted',
16
+ :nil => '%s must not be nil',
17
+ :blank => '%s must not be blank',
18
+ :length_between => '%s must be between %s and %s characters long',
19
+ :too_long => '%s must be at most %s characters long',
20
+ :too_short => '%s must be at least %s characters long',
21
+ :wrong_length => '%s must be %s characters long',
22
+ :taken => '%s is already taken',
23
+ :not_a_number => '%s must be a number',
24
+ :not_an_integer => '%s must be an integer',
25
+ :greater_than => '%s must be greater than %s',
26
+ :greater_than_or_equal_to => '%s must be greater than or equal to %s',
27
+ :equal_to => '%s must be equal to %s',
28
+ :not_equal_to => '%s must not be equal to %s',
29
+ :less_than => '%s must be less than %s',
30
+ :less_than_or_equal_to => '%s must be less than or equal to %s',
31
+ :value_between => '%s must be between %s and %s',
32
+ :primitive => '%s must be of type %s'
33
+ }
34
+
35
+ # Holds a hash with all the default error messages that can be replaced by your own copy or localizations.
36
+ def self.default_error_messages=(default_error_messages)
37
+ @@default_error_messages = default_error_messages
38
+ end
39
+
40
+ def self.default_error_message(key, field, *values)
41
+ field = DataMapper::Inflector.humanize(field)
42
+ @@default_error_messages[key] % [field, *values].flatten
43
+ end
44
+
45
+ attr_reader :resource
46
+
47
+ def initialize(resource)
48
+ @resource = resource
49
+ @errors = DataMapper::Validations::OrderedHash.new { |h,k| h[k] = [] }
50
+ end
51
+
52
+ # Clear existing validation errors.
53
+ def clear!
54
+ errors.clear
55
+ end
56
+
57
+ # Add a validation error. Use the field_name :general if the errors
58
+ # does not apply to a specific field of the Resource.
59
+ #
60
+ # @param [Symbol] field_name
61
+ # The name of the field that caused the error
62
+ #
63
+ # @param [String] message
64
+ # The message to add
65
+ def add(field_name, message)
66
+ # see 6abe8fff in extlib, but don't enforce
67
+ # it unless Edge version is installed
68
+ if message.respond_to?(:try_call)
69
+ # DM resource
70
+ message = if (resource.respond_to?(:model) &&
71
+ resource.model.respond_to?(:properties))
72
+ message.try_call(
73
+ resource,
74
+ resource.model.properties[field_name]
75
+ )
76
+ else
77
+ # pure Ruby object
78
+ message.try_call(resource)
79
+ end
80
+ end
81
+
82
+ (errors[field_name] ||= []) << message
83
+ end
84
+
85
+ # Collect all errors into a single list.
86
+ def full_messages
87
+ errors.inject([]) do |list, pair|
88
+ list += pair.last
89
+ end
90
+ end
91
+
92
+ # Return validation errors for a particular field_name.
93
+ #
94
+ # @param [Symbol] field_name
95
+ # The name of the field you want an error for.
96
+ #
97
+ # @return [Array<DataMapper::Validations::Error>]
98
+ # Array of validation errors or empty array, if there are no errors
99
+ # on given field
100
+ def on(field_name)
101
+ errors_for_field = errors[field_name]
102
+ DataMapper::Ext.blank?(errors_for_field) ? nil : errors_for_field.uniq
103
+ end
104
+
105
+ def each
106
+ errors.each_value do |v|
107
+ yield(v) unless DataMapper::Ext.blank?(v)
108
+ end
109
+ end
110
+
111
+ def empty?
112
+ @errors.all? { |property_name, errors| errors.empty? }
113
+ end
114
+
115
+ def method_missing(meth, *args, &block)
116
+ errors.send(meth, *args, &block)
117
+ end
118
+
119
+ def respond_to?(method)
120
+ super || errors.respond_to?(method)
121
+ end
122
+
123
+ def [](property_name)
124
+ if (property_errors = errors[property_name.to_sym])
125
+ property_errors
126
+ end
127
+ end
128
+
129
+ private
130
+
131
+ def errors
132
+ @errors
133
+ end
134
+
135
+ end # class ValidationErrors
136
+ end # module Validations
137
+ end # module DataMapper
@@ -0,0 +1,58 @@
1
+ module DataMapper
2
+ module Validations
3
+ #
4
+ # @author Guy van den Berg
5
+ # @since 0.9
6
+ class AbsenceValidator < GenericValidator
7
+
8
+ def call(target)
9
+ value = target.validation_property_value(field_name)
10
+ return true if DataMapper::Ext.blank?(value)
11
+
12
+ error_message = (
13
+ self.options[:message] || ValidationErrors.default_error_message(
14
+ :absent, field_name
15
+ )
16
+ )
17
+
18
+ add_error(target, error_message, field_name)
19
+ false
20
+ end
21
+
22
+ end # class AbsenceValidator
23
+
24
+ module ValidatesAbsence
25
+ extend Deprecate
26
+
27
+ # Validates that the specified attribute is "blank" via the
28
+ # attribute's #blank? method.
29
+ #
30
+ # @note
31
+ # dm-core's support lib adds the #blank? method to many classes,
32
+ # @see lib/dm-core/support/blank.rb (dm-core) for more information.
33
+ #
34
+ # @example [Usage]
35
+ # require 'dm-validations'
36
+ #
37
+ # class Page
38
+ # include DataMapper::Resource
39
+ #
40
+ # property :unwanted_attribute, String
41
+ # property :another_unwanted, String
42
+ # property :yet_again, String
43
+ #
44
+ # validates_absence_of :unwanted_attribute
45
+ # validates_absence_of :another_unwanted, :yet_again
46
+ #
47
+ # # a call to valid? will return false unless
48
+ # # all three attributes are blank
49
+ # end
50
+ #
51
+ def validates_absence_of(*fields)
52
+ validators.add(AbsenceValidator, *fields)
53
+ end
54
+
55
+ deprecate :validates_absent, :validates_absence_of
56
+ end # module ValidatesAbsent
57
+ end # module Validations
58
+ end # module DataMapper
@@ -0,0 +1,79 @@
1
+ module DataMapper
2
+ module Validations
3
+ # @author Martin Kihlgren
4
+ # @since 0.9
5
+ class AcceptanceValidator < GenericValidator
6
+
7
+ def initialize(field_name, options = {})
8
+ super
9
+
10
+ @options[:allow_nil] = true unless @options.key?(:allow_nil)
11
+
12
+ @options[:accept] ||= [ '1', 1, 'true', true, 't' ]
13
+ @options[:accept] = Array(@options[:accept])
14
+ end
15
+
16
+ def call(target)
17
+ return true if valid?(target)
18
+
19
+ error_message = (
20
+ @options[:message] || ValidationErrors.default_error_message(
21
+ :accepted, field_name
22
+ )
23
+ )
24
+ add_error(target, error_message, field_name)
25
+
26
+ false
27
+ end
28
+
29
+ private
30
+
31
+ def valid?(target)
32
+ value = target.validation_property_value(field_name)
33
+ return true if allow_nil?(value)
34
+ @options[:accept].include?(value)
35
+ end
36
+
37
+ def allow_nil?(value)
38
+ @options[:allow_nil] && value.nil?
39
+ end
40
+
41
+ end # class AcceptanceValidator
42
+
43
+ module ValidatesAcceptance
44
+ extend Deprecate
45
+
46
+ # Validates that the attributes's value is in the set of accepted
47
+ # values.
48
+ #
49
+ # @option [Boolean] :allow_nil (true)
50
+ # true if nil is allowed, false if not allowed.
51
+ #
52
+ # @option [Array] :accept (["1", 1, "true", true, "t"])
53
+ # A list of accepted values.
54
+ #
55
+ # @example Usage
56
+ # require 'dm-validations'
57
+ #
58
+ # class Page
59
+ # include DataMapper::Resource
60
+ #
61
+ # property :license_agreement_accepted, String
62
+ # property :terms_accepted, String
63
+ # validates_acceptance_of :license_agreement, :accept => "1"
64
+ # validates_acceptance_of :terms_accepted, :allow_nil => false
65
+ #
66
+ # # a call to valid? will return false unless:
67
+ # # license_agreement is nil or "1"
68
+ # # and
69
+ # # terms_accepted is one of ["1", 1, "true", true, "t"]
70
+ #
71
+ def validates_acceptance_of(*fields)
72
+ validators.add(AcceptanceValidator, *fields)
73
+ end
74
+
75
+ deprecate :validates_is_accepted, :validates_acceptance_of
76
+
77
+ end # module ValidatesIsAccepted
78
+ end # module Validations
79
+ end # module DataMapper
@@ -0,0 +1,61 @@
1
+ module DataMapper
2
+ module Validations
3
+ # @author teamon
4
+ # @since 0.9
5
+ module ValidatesWithBlock
6
+ # Validate using the given block. The block given needs to return:
7
+ # [result::<Boolean>, Error Message::<String>]
8
+ #
9
+ # @example [Usage]
10
+ # require 'dm-validations'
11
+ #
12
+ # class Page
13
+ # include DataMapper::Resource
14
+ #
15
+ # property :zip_code, String
16
+ #
17
+ # validates_with_block do
18
+ # if @zip_code == "94301"
19
+ # true
20
+ # else
21
+ # [false, "You're in the wrong zip code"]
22
+ # end
23
+ # end
24
+ #
25
+ # # A call to valid? will return false and
26
+ # # populate the object's errors with "You're in the
27
+ # # wrong zip code" unless zip_code == "94301"
28
+ #
29
+ # # You can also specify field:
30
+ #
31
+ # validates_with_block :zip_code do
32
+ # if @zip_code == "94301"
33
+ # true
34
+ # else
35
+ # [false, "You're in the wrong zip code"]
36
+ # end
37
+ # end
38
+ #
39
+ # # it will add returned error message to :zip_code field
40
+ #
41
+ def validates_with_block(*fields, &block)
42
+ @__validates_with_block_count ||= 0
43
+ @__validates_with_block_count += 1
44
+
45
+ # create method and pass it to MethodValidator
46
+ unless block_given?
47
+ raise ArgumentError, 'You need to pass a block to validates_with_block method'
48
+ end
49
+
50
+ method_name = "__validates_with_block_#{@__validates_with_block_count}".to_sym
51
+ define_method(method_name, &block)
52
+
53
+ options = fields.last.is_a?(Hash) ? fields.last.pop.dup : {}
54
+ options[:method] = method_name
55
+ fields = [method_name] if fields.empty?
56
+
57
+ validators.add(MethodValidator, *fields + [options])
58
+ end
59
+ end # module ValidatesWithMethod
60
+ end # module Validations
61
+ end # module DataMapper
@@ -0,0 +1,92 @@
1
+ # -*- coding: utf-8 -*-
2
+ module DataMapper
3
+ module Validations
4
+ # @author Guy van den Berg
5
+ # @since 0.9
6
+ class ConfirmationValidator < GenericValidator
7
+
8
+ def initialize(field_name, options = {})
9
+ super
10
+
11
+ set_optional_by_default
12
+
13
+ @confirm_field_name = (
14
+ options[:confirm] || "#{field_name}_confirmation"
15
+ ).to_sym
16
+ end
17
+
18
+ def call(target)
19
+ return true if valid?(target)
20
+
21
+ error_message = (
22
+ @options[:message] || ValidationErrors.default_error_message(
23
+ :confirmation, field_name
24
+ )
25
+ )
26
+ add_error(target, error_message, field_name)
27
+
28
+ false
29
+ end
30
+
31
+ private
32
+
33
+ def valid?(target)
34
+ value = target.validation_property_value(field_name)
35
+ return true if optional?(value)
36
+
37
+ if target.model.properties.named?(field_name)
38
+ return true unless target.attribute_dirty?(field_name)
39
+ end
40
+
41
+ confirm_value = target.instance_variable_get("@#{@confirm_field_name}")
42
+ value == confirm_value
43
+ end
44
+
45
+ end # class ConfirmationValidator
46
+
47
+ module ValidatesConfirmation
48
+ extend Deprecate
49
+
50
+ ##
51
+ # Validates that the given attribute is confirmed by another
52
+ # attribute. A common use case scenario is when you require a user to
53
+ # confirm their password, for which you use both password and
54
+ # password_confirmation attributes.
55
+ #
56
+ # @option [Boolean] :allow_nil (true)
57
+ # true or false.
58
+ #
59
+ # @option [Boolean] :allow_blank (true)
60
+ # true or false.
61
+ #
62
+ # @option [Symbol] :confirm (firstattr_confirmation)
63
+ # The attribute that you want to validate against.
64
+ #
65
+ # @example Usage
66
+ # require 'dm-validations'
67
+ #
68
+ # class Page
69
+ # include DataMapper::Resource
70
+ #
71
+ # property :password, String
72
+ # property :email, String
73
+ # attr_accessor :password_confirmation
74
+ # attr_accessor :email_repeated
75
+ #
76
+ # validates_confirmation_of :password
77
+ # validates_confirmation_of :email, :confirm => :email_repeated
78
+ #
79
+ # # a call to valid? will return false unless:
80
+ # # password == password_confirmation
81
+ # # and
82
+ # # email == email_repeated
83
+ #
84
+ def validates_confirmation_of(*fields)
85
+ validators.add(ConfirmationValidator, *fields)
86
+ end
87
+
88
+ deprecate :validates_is_confirmed, :validates_confirmation_of
89
+
90
+ end # module ValidatesIsConfirmed
91
+ end # module Validations
92
+ end # module DataMapper
@@ -0,0 +1,124 @@
1
+ #require File.dirname(__FILE__) + '/formats/email'
2
+
3
+ require 'pathname'
4
+ require 'dm-validations/formats/email'
5
+ require 'dm-validations/formats/url'
6
+
7
+ module DataMapper
8
+ module Validations
9
+ class UnknownValidationFormat < ::ArgumentError; end
10
+
11
+ # @author Guy van den Berg
12
+ # @since 0.9
13
+ class FormatValidator < GenericValidator
14
+
15
+ FORMATS = {}
16
+
17
+ include DataMapper::Validations::Format::Email
18
+ include DataMapper::Validations::Format::Url
19
+
20
+ def initialize(field_name, options = {})
21
+ super
22
+
23
+ set_optional_by_default
24
+ end
25
+
26
+ def call(target)
27
+ return true if valid?(target)
28
+
29
+ value = target.validation_property_value(field_name)
30
+
31
+ error_message = (
32
+ @options[:message] || ValidationErrors.default_error_message(
33
+ :invalid, field_name
34
+ )
35
+ )
36
+
37
+ add_error(
38
+ target,
39
+ error_message.try_call(humanized_field_name, value),
40
+ field_name
41
+ )
42
+ false
43
+ end
44
+
45
+ private
46
+
47
+ def valid?(target)
48
+ value = target.validation_property_value(field_name)
49
+ return true if optional?(value)
50
+
51
+ validation = @options[:as] || @options[:with]
52
+
53
+ if validation.is_a?(Symbol) && !FORMATS.has_key?(validation)
54
+ raise("No such predefined format '#{validation}'")
55
+ end
56
+
57
+ validator = if validation.is_a?(Symbol)
58
+ FORMATS[validation][0]
59
+ else
60
+ validation
61
+ end
62
+
63
+ case validator
64
+ when Proc then validator.call(value)
65
+ when Regexp then value ? value.to_s =~ validator : false
66
+ else
67
+ raise(UnknownValidationFormat, "Can't determine how to validate #{target.class}##{field_name} with #{validator.inspect}")
68
+ end
69
+ rescue Encoding::CompatibilityError
70
+ # This is to work around a bug in jruby - see formats/email.rb
71
+ false
72
+ end
73
+
74
+ end # class FormatValidator
75
+
76
+ module ValidatesFormat
77
+ extend Deprecate
78
+
79
+ # Validates that the attribute is in the specified format. You may
80
+ # use the :as (or :with, it's an alias) option to specify the
81
+ # pre-defined format that you want to validate against. You may also
82
+ # specify your own format via a Proc or Regexp passed to the the :as
83
+ # or :with options.
84
+ #
85
+ # @option [Boolean] :allow_nil (true)
86
+ # true or false.
87
+ #
88
+ # @option [Boolean] :allow_blank (true)
89
+ # true or false.
90
+ #
91
+ # @option [Format, Proc, Regexp] :as
92
+ # The pre-defined format, Proc or Regexp to validate against.
93
+ #
94
+ # @option [Format, Proc, Regexp] :with
95
+ # An alias for :as.
96
+ #
97
+ # :email_address (format is specified in DataMapper::Validations::Format::Email - note that unicode emails will *not* be matched under MRI1.8.7)
98
+ # :url (format is specified in DataMapper::Validations::Format::Url)
99
+ #
100
+ # @example Usage
101
+ # require 'dm-validations'
102
+ #
103
+ # class Page
104
+ # include DataMapper::Resource
105
+ #
106
+ # property :email, String
107
+ # property :zip_code, String
108
+ #
109
+ # validates_format_of :email, :as => :email_address
110
+ # validates_format_of :zip_code, :with => /^\d{5}$/
111
+ #
112
+ # # a call to valid? will return false unless:
113
+ # # email is formatted like an email address
114
+ # # and
115
+ # # zip_code is a string of 5 digits
116
+ #
117
+ def validates_format_of(*fields)
118
+ validators.add(FormatValidator, *fields)
119
+ end
120
+
121
+ deprecate :validates_format, :validates_format_of
122
+ end # module ValidatesFormat
123
+ end # module Validations
124
+ end # module DataMapper