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.
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