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.
Files changed (159) hide show
  1. data/{History.txt → History.rdoc} +10 -3
  2. data/LICENSE +1 -0
  3. data/Manifest.txt +103 -33
  4. data/README.rdoc +172 -0
  5. data/Rakefile +4 -5
  6. data/lib/dm-validations.rb +73 -75
  7. data/lib/dm-validations/auto_validate.rb +98 -56
  8. data/lib/dm-validations/contextual_validators.rb +37 -14
  9. data/lib/dm-validations/exceptions.rb +3 -0
  10. data/lib/dm-validations/formats/url.rb +3 -1
  11. data/lib/dm-validations/support/context.rb +54 -0
  12. data/lib/dm-validations/validation_errors.rb +51 -27
  13. data/lib/dm-validations/{absent_field_validator.rb → validators/absent_field_validator.rb} +2 -8
  14. data/lib/dm-validations/{acceptance_validator.rb → validators/acceptance_validator.rb} +7 -7
  15. data/lib/dm-validations/{block_validator.rb → validators/block_validator.rb} +0 -0
  16. data/lib/dm-validations/{confirmation_validator.rb → validators/confirmation_validator.rb} +7 -7
  17. data/lib/dm-validations/{format_validator.rb → validators/format_validator.rb} +10 -16
  18. data/lib/dm-validations/{generic_validator.rb → validators/generic_validator.rb} +28 -6
  19. data/lib/dm-validations/validators/length_validator.rb +214 -0
  20. data/lib/dm-validations/validators/method_validator.rb +68 -0
  21. data/lib/dm-validations/validators/numeric_validator.rb +171 -0
  22. data/lib/dm-validations/{primitive_validator.rb → validators/primitive_validator.rb} +2 -7
  23. data/lib/dm-validations/{required_field_validator.rb → validators/required_field_validator.rb} +0 -6
  24. data/lib/dm-validations/{uniqueness_validator.rb → validators/uniqueness_validator.rb} +9 -20
  25. data/lib/dm-validations/{within_validator.rb → validators/within_validator.rb} +4 -4
  26. data/lib/dm-validations/version.rb +1 -1
  27. data/spec/fixtures/barcode.rb +32 -0
  28. data/spec/fixtures/basketball_court.rb +58 -0
  29. data/spec/fixtures/basketball_player.rb +37 -0
  30. data/spec/fixtures/beta_tester_account.rb +33 -0
  31. data/spec/fixtures/bill_of_landing.rb +42 -0
  32. data/spec/fixtures/boat_dock.rb +26 -0
  33. data/spec/fixtures/city.rb +25 -0
  34. data/spec/fixtures/company.rb +95 -0
  35. data/spec/fixtures/corporate_world.rb +47 -0
  36. data/spec/fixtures/country.rb +25 -0
  37. data/spec/fixtures/currency.rb +42 -0
  38. data/spec/fixtures/ethernet_frame.rb +56 -0
  39. data/spec/fixtures/event.rb +44 -0
  40. data/spec/fixtures/g3_concert.rb +57 -0
  41. data/spec/fixtures/jabberwock.rb +27 -0
  42. data/spec/fixtures/kayak.rb +28 -0
  43. data/spec/fixtures/lernean_hydra.rb +39 -0
  44. data/spec/fixtures/mathematical_function.rb +34 -0
  45. data/spec/fixtures/memory_object.rb +30 -0
  46. data/spec/fixtures/mittelschnauzer.rb +35 -0
  47. data/spec/fixtures/motor_launch.rb +21 -0
  48. data/spec/fixtures/page.rb +32 -0
  49. data/spec/fixtures/phone_number.rb +28 -0
  50. data/spec/fixtures/pirogue.rb +28 -0
  51. data/spec/fixtures/programming_language.rb +83 -0
  52. data/spec/fixtures/reservation.rb +38 -0
  53. data/spec/fixtures/scm_operation.rb +67 -0
  54. data/spec/fixtures/sms_message.rb +22 -0
  55. data/spec/fixtures/udp_packet.rb +49 -0
  56. data/spec/integration/absent_field_validator/absent_field_validator_spec.rb +86 -0
  57. data/spec/integration/absent_field_validator/spec_helper.rb +7 -0
  58. data/spec/integration/acceptance_validator/acceptance_validator_spec.rb +196 -0
  59. data/spec/integration/acceptance_validator/spec_helper.rb +7 -0
  60. data/spec/integration/automatic_validation/custom_messages_for_inferred_validation_spec.rb +47 -0
  61. data/spec/integration/automatic_validation/disabling_inferred_validation_spec.rb +41 -0
  62. data/spec/integration/automatic_validation/inferred_boolean_properties_validation_spec.rb +104 -0
  63. data/spec/integration/automatic_validation/inferred_float_property_validation_spec.rb +35 -0
  64. data/spec/integration/automatic_validation/inferred_format_validation_spec.rb +33 -0
  65. data/spec/integration/automatic_validation/inferred_integer_properties_validation_spec.rb +73 -0
  66. data/spec/integration/automatic_validation/inferred_length_validation_spec.rb +121 -0
  67. data/spec/integration/automatic_validation/inferred_presence_validation_spec.rb +41 -0
  68. data/spec/integration/automatic_validation/inferred_primitive_validation_spec.rb +20 -0
  69. data/spec/integration/automatic_validation/inferred_within_validation_spec.rb +33 -0
  70. data/spec/integration/automatic_validation/spec_helper.rb +74 -0
  71. data/spec/integration/block_validator/block_validator_spec.rb +32 -0
  72. data/spec/integration/block_validator/spec_helper.rb +5 -0
  73. data/spec/integration/conditional_validation/if_condition_spec.rb +61 -0
  74. data/spec/integration/conditional_validation/spec_helper.rb +5 -0
  75. data/spec/integration/confirmation_validator/confirmation_validator_spec.rb +74 -0
  76. data/spec/integration/confirmation_validator/spec_helper.rb +5 -0
  77. data/spec/integration/datamapper_models/association_validation_spec.rb +23 -0
  78. data/spec/integration/datamapper_models/inheritance_spec.rb +78 -0
  79. data/spec/integration/duplicated_validations/duplicated_validations_spec.rb +22 -0
  80. data/spec/integration/duplicated_validations/spec_helper.rb +5 -0
  81. data/spec/integration/format_validator/email_format_validator_spec.rb +113 -0
  82. data/spec/integration/format_validator/format_validator_spec.rb +60 -0
  83. data/spec/integration/format_validator/regexp_validator_spec.rb +29 -0
  84. data/spec/integration/format_validator/spec_helper.rb +5 -0
  85. data/spec/integration/format_validator/url_format_validator_spec.rb +63 -0
  86. data/spec/integration/length_validator/default_value_spec.rb +12 -0
  87. data/spec/integration/length_validator/equality_spec.rb +79 -0
  88. data/spec/integration/length_validator/error_message_spec.rb +15 -18
  89. data/spec/integration/length_validator/maximum_spec.rb +40 -24
  90. data/spec/integration/length_validator/minimum_spec.rb +32 -21
  91. data/spec/integration/length_validator/range_spec.rb +50 -60
  92. data/spec/integration/length_validator/spec_helper.rb +7 -12
  93. data/spec/integration/method_validator/method_validator_spec.rb +239 -0
  94. data/spec/integration/method_validator/spec_helper.rb +5 -0
  95. data/spec/integration/numeric_validator/equality_with_float_type_spec.rb +61 -0
  96. data/spec/integration/numeric_validator/equality_with_integer_type_spec.rb +37 -0
  97. data/spec/integration/numeric_validator/float_type_spec.rb +42 -56
  98. data/spec/integration/numeric_validator/gt_with_float_type_spec.rb +35 -0
  99. data/spec/integration/numeric_validator/gte_with_float_type_spec.rb +35 -0
  100. data/spec/integration/numeric_validator/integer_only_true_spec.rb +3 -6
  101. data/spec/integration/numeric_validator/integer_type_spec.rb +8 -24
  102. data/spec/integration/numeric_validator/lt_with_float_type_spec.rb +35 -0
  103. data/spec/integration/numeric_validator/lte_with_float_type_spec.rb +35 -0
  104. data/spec/integration/numeric_validator/spec_helper.rb +5 -77
  105. data/spec/integration/primitive_validator/primitive_validator_spec.rb +90 -0
  106. data/spec/integration/primitive_validator/spec_helper.rb +5 -0
  107. data/spec/integration/pure_ruby_objects/plain_old_ruby_object_validation_spec.rb +118 -0
  108. data/spec/integration/required_field_validator/association_spec.rb +5 -8
  109. data/spec/integration/required_field_validator/boolean_type_value_spec.rb +4 -7
  110. data/spec/integration/required_field_validator/date_type_value_spec.rb +3 -6
  111. data/spec/integration/required_field_validator/datetime_type_value_spec.rb +3 -6
  112. data/spec/integration/required_field_validator/float_type_value_spec.rb +3 -6
  113. data/spec/integration/required_field_validator/integer_type_value_spec.rb +2 -5
  114. data/spec/integration/required_field_validator/plain_old_ruby_object_spec.rb +5 -8
  115. data/spec/integration/required_field_validator/shared_examples.rb +1 -1
  116. data/spec/integration/required_field_validator/spec_helper.rb +6 -67
  117. data/spec/integration/required_field_validator/string_type_value_spec.rb +2 -5
  118. data/spec/integration/required_field_validator/text_type_value_spec.rb +2 -5
  119. data/spec/integration/shared/default_validation_context.rb +13 -0
  120. data/spec/integration/shared/valid_and_invalid_model.rb +27 -0
  121. data/spec/integration/uniqueness_validator/spec_helper.rb +5 -0
  122. data/spec/integration/uniqueness_validator/uniqueness_validator_spec.rb +114 -0
  123. data/spec/integration/within_validator/spec_helper.rb +5 -0
  124. data/spec/integration/within_validator/within_validator_spec.rb +164 -0
  125. data/spec/public/resource_spec.rb +68 -0
  126. data/spec/spec.opts +1 -0
  127. data/spec/spec_helper.rb +12 -4
  128. data/spec/unit/contextual_validators/emptiness_spec.rb +50 -0
  129. data/spec/unit/contextual_validators/execution_spec.rb +55 -0
  130. data/spec/unit/contextual_validators/spec_helper.rb +37 -0
  131. data/spec/unit/generic_validator/equality_operator_spec.rb +26 -0
  132. data/spec/unit/validation_errors/adding_spec.rb +54 -0
  133. data/spec/unit/validation_errors/emptiness_spec.rb +38 -0
  134. data/spec/unit/validation_errors/enumerable_spec.rb +32 -0
  135. data/tasks/install.rb +1 -1
  136. data/tasks/spec.rb +4 -4
  137. metadata +118 -55
  138. data/README.txt +0 -72
  139. data/lib/dm-validations/custom_validator.rb +0 -72
  140. data/lib/dm-validations/length_validator.rb +0 -113
  141. data/lib/dm-validations/method_validator.rb +0 -68
  142. data/lib/dm-validations/numeric_validator.rb +0 -83
  143. data/spec/integration/absent_field_validator_spec.rb +0 -36
  144. data/spec/integration/acceptance_validator_spec.rb +0 -87
  145. data/spec/integration/auto_validate_spec.rb +0 -342
  146. data/spec/integration/block_validator_spec.rb +0 -30
  147. data/spec/integration/confirmation_validator_spec.rb +0 -105
  148. data/spec/integration/contextual_validators_spec.rb +0 -27
  149. data/spec/integration/custom_validator_spec.rb +0 -9
  150. data/spec/integration/format_validator_spec.rb +0 -193
  151. data/spec/integration/generic_validator_spec.rb +0 -17
  152. data/spec/integration/length_validator/valid_objects_spec.rb +0 -13
  153. data/spec/integration/method_validator_spec.rb +0 -58
  154. data/spec/integration/numeric_validator_spec.rb +0 -253
  155. data/spec/integration/primitive_validator_spec.rb +0 -30
  156. data/spec/integration/uniqueness_validator_spec.rb +0 -97
  157. data/spec/integration/validation_errors_spec.rb +0 -18
  158. data/spec/integration/validation_spec.rb +0 -404
  159. data/spec/integration/within_validator_spec.rb +0 -79
@@ -1,113 +0,0 @@
1
- module DataMapper
2
- module Validate
3
-
4
- ##
5
- #
6
- # @author Guy van den Berg
7
- # @since 0.9
8
- class LengthValidator < GenericValidator
9
-
10
- def initialize(field_name, options)
11
- super
12
- @field_name = field_name
13
- @options = options
14
-
15
- @min = options[:minimum] || options[:min]
16
- @max = options[:maximum] || options[:max]
17
- @equal = options[:is] || options[:equals]
18
- @range = options[:within] || options[:in]
19
-
20
- @validation_method ||= :range if @range
21
- @validation_method ||= :min if @min && @max.nil?
22
- @validation_method ||= :max if @max && @min.nil?
23
- @validation_method ||= :equals unless @equal.nil?
24
- end
25
-
26
- def call(target)
27
- field_value = target.validation_property_value(field_name)
28
- return true if @options[:allow_nil] && field_value.nil?
29
-
30
- field_value = '' if field_value.nil?
31
-
32
- # XXX: HACK seems hacky to do this on every validation, probably should
33
- # do this elsewhere?
34
- field = Extlib::Inflection.humanize(field_name)
35
- min = @range ? @range.min : @min
36
- max = @range ? @range.max : @max
37
- equal = @equal
38
-
39
- case @validation_method
40
- when :range then
41
- unless valid = @range.include?(field_value.size)
42
- error_message = ValidationErrors.default_error_message(:length_between, field, min, max)
43
- end
44
- when :min then
45
- unless valid = field_value.size >= min
46
- error_message = ValidationErrors.default_error_message(:too_short, field, min)
47
- end
48
- when :max then
49
- unless valid = field_value.size <= max
50
- error_message = ValidationErrors.default_error_message(:too_long, field, max)
51
- end
52
- when :equals then
53
- unless valid = field_value.size == equal
54
- error_message = ValidationErrors.default_error_message(:wrong_length, field, equal)
55
- end
56
- end
57
-
58
- error_message = @options[:message] || error_message
59
-
60
- add_error(target, error_message, field_name) unless valid
61
-
62
- return valid
63
- end
64
-
65
- end # class LengthValidator
66
-
67
- module ValidatesLength
68
-
69
- # Validates that the length of the attribute is equal to, less than,
70
- # greater than or within a certain range (depending upon the options
71
- # you specify).
72
- #
73
- # @option :allow_nil<Boolean> true/false (default is true)
74
- # @option :minimum ensures that the attribute's length is greater than
75
- # or equal to the supplied value
76
- # @option :min alias for :minimum
77
- # @option :maximum ensures the attribute's length is less than or equal
78
- # to the supplied value
79
- # @option :max alias for :maximum
80
- # @option :equals ensures the attribute's length is equal to the
81
- # supplied value
82
- # @option :is alias for :equals
83
- # @option :in<Range> given a Range, ensures that the attributes length is
84
- # include?'ed in the Range
85
- # @option :within<Range> alias for :in
86
- #
87
- # @example [Usage]
88
- # require 'dm-validations'
89
- #
90
- # class Page
91
- # include DataMapper::Resource
92
- #
93
- # property high, Integer
94
- # property low, Integer
95
- # property just_right, Integer
96
- #
97
- # validates_length :high, :min => 100000000000
98
- # validates_length :low, :equals => 0
99
- # validates_length :just_right, :within => 1..10
100
- #
101
- # # a call to valid? will return false unless:
102
- # # high is greater than or equal to 100000000000
103
- # # low is equal to 0
104
- # # just_right is between 1 and 10 (inclusive of both 1 and 10)
105
- #
106
- def validates_length(*fields)
107
- opts = opts_from_validator_args(fields)
108
- add_validator_to_context(opts, fields, DataMapper::Validate::LengthValidator)
109
- end
110
-
111
- end # module ValidatesLength
112
- end # module Validate
113
- end # module DataMapper
@@ -1,68 +0,0 @@
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
- @field_name, @options = field_name, options.clone
13
- @options[:method] = @field_name unless @options.has_key?(:method)
14
- end
15
-
16
- def call(target)
17
- result, message = target.send(@options[:method])
18
- add_error(target, message, field_name) unless result
19
- result
20
- end
21
-
22
- def ==(other)
23
- @options[:method] == other.instance_variable_get(:@options)[:method] && super
24
- end
25
- end # class MethodValidator
26
-
27
- module ValidatesWithMethod
28
-
29
- ##
30
- # Validate using the given method. The method given needs to return:
31
- # [result::<Boolean>, Error Message::<String>]
32
- #
33
- # @example [Usage]
34
- # require 'dm-validations'
35
- #
36
- # class Page
37
- # include DataMapper::Resource
38
- #
39
- # property :zip_code, String
40
- #
41
- # validates_with_method :in_the_right_location?
42
- #
43
- # def in_the_right_location?
44
- # if @zip_code == "94301"
45
- # return true
46
- # else
47
- # return [false, "You're in the wrong zip code"]
48
- # end
49
- # end
50
- #
51
- # # A call to valid? will return false and
52
- # # populate the object's errors with "You're in the
53
- # # wrong zip code" unless zip_code == "94301"
54
- #
55
- # # You can also specify field:
56
- #
57
- # validates_with_method :zip_code, :in_the_right_location?
58
- #
59
- # # it will add returned error message to :zip_code field
60
- #
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
@@ -1,83 +0,0 @@
1
- module DataMapper
2
- module Validate
3
-
4
- ##
5
- #
6
- # @author Guy van den Berg
7
- # @since 0.9
8
- class NumericValidator < GenericValidator
9
-
10
- def initialize(field_name, options={})
11
- super
12
- @field_name, @options = field_name, options
13
- @options[:integer_only] = false unless @options.has_key?(:integer_only)
14
- end
15
-
16
- def call(target)
17
- value = target.send(field_name)
18
- return true if @options[:allow_nil] && value.nil?
19
-
20
- value = value.kind_of?(BigDecimal) ? value.to_s('F') : value.to_s
21
-
22
- error_message = @options[:message]
23
- precision = @options[:precision]
24
- scale = @options[:scale]
25
-
26
- if @options[:integer_only]
27
- return true if value =~ /\A[+-]?\d+\z/
28
- error_message ||= ValidationErrors.default_error_message(:not_an_integer, field_name)
29
- else
30
- # FIXME: if precision and scale are not specified, can we assume that it is an integer?
31
- # probably not, as floating point numbers don't have hard
32
- # defined scale. the scale floats with the length of the
33
- # integral and precision. Ie. if precision = 10 and integral
34
- # portion of the number is 9834 (4 digits), the max scale will
35
- # be 6 (10 - 4). But if the integral length is 1, max scale
36
- # will be (10 - 1) = 9, so 1.234567890.
37
- # In MySQL somehow you can hard-define scale on floats. Not
38
- # quite sure how that works...
39
- if precision && scale
40
- #handles both Float when it has scale specified and BigDecimal
41
- if precision > scale && scale > 0
42
- return true if value =~ /\A[+-]?(?:\d{1,#{precision - scale}}|\d{0,#{precision - scale}}\.\d{1,#{scale}})\z/
43
- elsif precision > scale && scale == 0
44
- return true if value =~ /\A[+-]?(?:\d{1,#{precision}}(?:\.0)?)\z/
45
- elsif precision == scale
46
- return true if value =~ /\A[+-]?(?:0(?:\.\d{1,#{scale}})?)\z/
47
- else
48
- raise ArgumentError, "Invalid precision #{precision.inspect} and scale #{scale.inspect} for #{field_name} (value: #{value.inspect} #{value.class})"
49
- end
50
- elsif precision && scale.nil?
51
- # for floats, if scale is not set
52
-
53
- #total number of digits is less or equal precision
54
- return true if value.gsub(/[^\d]/, '').length <= precision
55
-
56
- #number of digits before decimal == precision, and the number is x.0. same as scale = 0
57
- return true if value =~ /\A[+-]?(?:\d{1,#{precision}}(?:\.0)?)\z/
58
- else
59
- return true if value =~ /\A[+-]?(?:\d+|\d*\.\d+)\z/
60
- end
61
- error_message ||= ValidationErrors.default_error_message(:not_a_number, field_name)
62
- end
63
-
64
- add_error(target, error_message, field_name)
65
-
66
- # TODO: check the gt, gte, lt, lte, and eq options
67
-
68
- return false
69
- end
70
- end # class NumericValidator
71
-
72
- module ValidatesIsNumber
73
-
74
- # Validate whether a field is numeric
75
- #
76
- def validates_is_number(*fields)
77
- opts = opts_from_validator_args(fields)
78
- add_validator_to_context(opts, fields, DataMapper::Validate::NumericValidator)
79
- end
80
-
81
- end # module ValidatesIsNumber
82
- end # module Validate
83
- end # module DataMapper
@@ -1,36 +0,0 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
-
4
- describe DataMapper::Validate::AbsentFieldValidator do
5
- before(:all) do
6
- class ::Kayak
7
- include DataMapper::Resource
8
- property :id, Integer, :key => true
9
- property :salesman, String, :auto_validation => false
10
- validates_absent :salesman, :when => :sold
11
- end
12
-
13
- class ::Pirogue
14
- include DataMapper::Resource
15
- property :id, Integer, :key => true
16
- property :salesman, String, :default => 'Layfayette'
17
- validates_absent :salesman, :when => :sold
18
- end
19
- end
20
-
21
- it "should validate the absence of a value on an instance of a resource" do
22
- kayak = Kayak.new
23
- kayak.valid_for_sold?.should == true
24
-
25
- kayak.salesman = 'Joe'
26
- kayak.valid_for_sold?.should_not == true
27
- kayak.errors.on(:salesman).should include('Salesman must be absent')
28
- end
29
-
30
- it "should validate the absence of a value and ensure defaults" do
31
- pirogue = Pirogue.new
32
- pirogue.should_not be_valid_for_sold
33
- pirogue.errors.on(:salesman).should include('Salesman must be absent')
34
- end
35
-
36
- end
@@ -1,87 +0,0 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
-
4
- describe DataMapper::Validate::AcceptanceValidator do
5
- describe "with standard options" do
6
- before(:all) do
7
- class ::SkimBat
8
- include DataMapper::Resource
9
- property :id, Integer, :serial => true
10
- property :sailyness, Boolean
11
- validates_is_accepted :sailyness
12
- end
13
- @s = SkimBat.new
14
- end
15
-
16
- it "should validate if a resource instance has been accepted" do
17
- @s.sailyness = "1"
18
- @s.valid?.should == true
19
- end
20
-
21
- it "should not validate if a resource instance has not been accepted" do
22
- @s.sailyness = "0"
23
- @s.valid?.should == false
24
- end
25
-
26
- it "should allow nil acceptance" do
27
- @s.sailyness = nil
28
- @s.valid?.should == true
29
- end
30
-
31
- it "should add the default message when invalid" do
32
- @s.sailyness = "0"
33
- @s.valid?.should == false
34
- @s.errors.on(:sailyness).should include('Sailyness is not accepted')
35
- end
36
- end
37
- describe "with :allow_nil => false" do
38
- before(:all) do
39
- SkimBat.class_eval do
40
- validators.clear!
41
- validates_is_accepted :sailyness, :allow_nil => false
42
- end
43
- @s = SkimBat.new
44
- end
45
-
46
- it "should not allow nil acceptance" do
47
- @s.sailyness = nil
48
- @s.valid?.should == false
49
- end
50
- end
51
-
52
- describe "with custom :accept" do
53
- before(:all) do
54
- SkimBat.class_eval do
55
- validators.clear!
56
- validates_is_accepted :sailyness, :accept => true
57
- end
58
- @s = SkimBat.new
59
- end
60
-
61
- it "should validate if a resource instance has been accepted" do
62
- @s.sailyness = "true"
63
- @s.valid?.should == true
64
- end
65
-
66
- it "should not validate if a resource instance has not been accepted" do
67
- @s.sailyness = "false"
68
- @s.valid?.should == false
69
- end
70
- end
71
-
72
- describe "with custom message" do
73
- before(:all) do
74
- SkimBat.class_eval do
75
- validators.clear!
76
- validates_is_accepted :sailyness, :message => "hehu!"
77
- end
78
- @s = SkimBat.new
79
- end
80
-
81
- it "should append the custom message when invalid" do
82
- @s.sailyness = "0"
83
- @s.valid?.should == false
84
- @s.errors.on(:sailyness).should include('hehu!')
85
- end
86
- end
87
- end
@@ -1,342 +0,0 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
-
4
- module TypecastBypassSetter
5
- # Bypass typecasting so we can set values for specs
6
- def set(attributes)
7
- attributes.each do |k, v|
8
- instance_variable_set("@#{k}", v)
9
- end
10
- end
11
- end
12
-
13
- class SailBoat
14
- include DataMapper::Resource
15
- property :id, Integer, :key => true
16
- property :name, String, :nullable => false, :validates => :presence_test
17
- property :description, String, :length => 10, :validates => :length_test_1
18
- property :notes, String, :length => 2..10, :validates => :length_test_2
19
- property :no_validation, String, :auto_validation => false
20
- property :salesman, String, :nullable => false, :validates => [:multi_context_1, :multi_context_2]
21
- property :code, String, :format => Proc.new { |code| code =~ /A\d{4}\z/ }, :validates => :format_test
22
- property :allow_nil, String, :size => 5..10, :nullable => true, :validates => :nil_test
23
- property :build_date, Date, :validates => :primitive_test
24
- property :float, Float, :precision => 2, :scale => 1
25
- property :big_decimal, BigDecimal, :precision => 2, :scale => 1
26
-
27
- include TypecastBypassSetter
28
- end
29
-
30
- class HasNullableBoolean
31
- include DataMapper::Resource
32
- property :id, Integer, :key => true
33
- property :bool, Boolean # :nullable => true by default
34
-
35
- include TypecastBypassSetter
36
- end
37
-
38
- class HasNotNullableBoolean
39
- include DataMapper::Resource
40
- property :id, Integer, :key => true
41
- property :bool, Boolean, :nullable => false
42
-
43
- include TypecastBypassSetter
44
- end
45
-
46
- class HasNotNullableParanoidBoolean
47
- include DataMapper::Resource
48
- property :id, Integer, :key => true
49
- property :bool, ParanoidBoolean, :nullable => false
50
-
51
- include TypecastBypassSetter
52
- end
53
-
54
- describe "Automatic Validation from Property Definition" do
55
- it "should have a hook for adding auto validations called from
56
- DataMapper::Property#new" do
57
- SailBoat.should respond_to(:auto_generate_validations)
58
- end
59
-
60
- it "should auto add a validates_is_present when property has option
61
- :nullable => false" do
62
- validator = SailBoat.validators.context(:presence_test).first
63
- validator.should be_kind_of(DataMapper::Validate::RequiredFieldValidator)
64
- validator.field_name.should == :name
65
-
66
- boat = SailBoat.new
67
- boat.valid_for_presence_test?.should == false
68
- boat.errors.on(:name).should include('Name must not be blank')
69
- boat.name = 'Float'
70
- boat.valid_for_presence_test?.should == true
71
- end
72
-
73
- it "should auto add a validates_length for maximum size on String properties" do
74
- # max length test max=10
75
- boat = SailBoat.new
76
- boat.valid_for_length_test_1?.should == true #no minimum length
77
- boat.description = 'ABCDEFGHIJK' #11
78
- boat.valid_for_length_test_1?.should == false
79
- boat.errors.on(:description).should include('Description must be less than 10 characters long')
80
- boat.description = 'ABCDEFGHIJ' #10
81
- boat.valid_for_length_test_1?.should == true
82
- end
83
-
84
- it "should auto add validates_length within a range when option :length
85
- or :size is a range" do
86
- # Range test notes = 2..10
87
- boat = SailBoat.new
88
- boat.should be_valid_for_length_test_2
89
- boat.notes = 'AB' #2
90
- boat.should be_valid_for_length_test_2
91
- boat.notes = 'ABCDEFGHIJK' #11
92
- boat.should_not be_valid_for_length_test_2
93
- boat.errors.on(:notes).should include('Notes must be between 2 and 10 characters long')
94
- boat.notes = 'ABCDEFGHIJ' #10
95
- boat.should be_valid_for_length_test_2
96
- end
97
-
98
- it "should auto add a validates_format if the :format option is given" do
99
- # format test - format = /A\d{4}\z/ on code
100
- boat = SailBoat.new
101
- boat.should be_valid_for_format_test
102
- boat.code = 'A1234'
103
- boat.should be_valid_for_format_test
104
- boat.code = 'BAD CODE'
105
- boat.should_not be_valid_for_format_test
106
- boat.errors.on(:code).should include('Code has an invalid format')
107
- end
108
-
109
- it "should auto validate all strings for max length" do
110
- klass = Class.new do
111
- include DataMapper::Resource
112
- property :id, Integer, :serial => true
113
- property :name, String
114
- end
115
- t = klass.new(:id => 1)
116
- t.should be_valid
117
- t.name = 'a' * 51
118
- t.should_not be_valid
119
- t.errors.on(:name).should include('Name must be less than 50 characters long')
120
- end
121
-
122
- it "should auto validate the primitive type" do
123
- validator = SailBoat.validators.context(:primitive_test).first
124
- validator.should be_kind_of(DataMapper::Validate::PrimitiveValidator)
125
- boat = SailBoat.new
126
- boat.should be_valid_for_primitive_test
127
- boat.build_date = 'ABC'
128
- boat.should_not be_valid_for_primitive_test
129
- boat.errors.on(:build_date).should include('Build date must be of type Date')
130
- end
131
-
132
- it "should not auto add any validators if the option :auto_validation => false was given" do
133
- klass = Class.new do
134
- include DataMapper::Resource
135
- property :id, Integer, :serial => true, :auto_validation => false
136
- property :name, String, :nullable => false, :auto_validation => false
137
- property :bool, DataMapper::Types::Boolean, :nullable => false, :auto_validation => false
138
- end
139
- klass.new.valid?.should == true
140
- end
141
-
142
- it "should auto add range checking the length of a string while still allowing null values" do
143
- boat = SailBoat.new
144
- boat.allow_nil = 'ABC'
145
- boat.should_not be_valid_for_nil_test
146
- boat.errors.on(:allow_nil).should include('Allow nil must be between 5 and 10 characters long')
147
-
148
- boat.allow_nil = 'ABCDEFG'
149
- boat.should be_valid_for_nil_test
150
-
151
- boat.allow_nil = 'ABCDEFGHIJKLMNOP'
152
- boat.should_not be_valid_for_nil_test
153
- boat.errors.on(:allow_nil).should include('Allow nil must be between 5 and 10 characters long')
154
-
155
- boat.allow_nil = nil
156
- boat.should be_valid_for_nil_test
157
- end
158
-
159
- describe 'for Integer properties' do
160
- before do
161
- @boat = SailBoat.new
162
- end
163
-
164
- it 'should allow integers' do
165
- @boat.set(:id => 1)
166
- @boat.should be_valid
167
- end
168
-
169
- it 'should not allow floats' do
170
- @boat.set(:id => 1.0)
171
- @boat.should_not be_valid
172
- @boat.errors.on(:id).should include('Id must be an integer')
173
- end
174
-
175
- it 'should not allow decimals' do
176
- @boat.set(:id => BigDecimal('1'))
177
- @boat.should_not be_valid
178
- @boat.errors.on(:id).should include('Id must be an integer')
179
- end
180
- end
181
-
182
- describe 'for nullable Boolean properties' do
183
- before do
184
- @boat = HasNullableBoolean.new(:id => 1)
185
- end
186
-
187
- it 'should allow true' do
188
- @boat.set(:bool => true)
189
- @boat.should be_valid
190
- end
191
-
192
- it 'should allow false' do
193
- @boat.set(:bool => false)
194
- @boat.should be_valid
195
- end
196
-
197
- it 'should allow nil' do
198
- @boat.set(:bool => nil)
199
- @boat.should be_valid
200
- end
201
- end
202
-
203
- describe 'for non-nullable Boolean properties' do
204
- before do
205
- @boat = HasNotNullableBoolean.new(:id => 1)
206
- end
207
-
208
- it 'should allow true' do
209
- @boat.set(:bool => true)
210
- @boat.should be_valid
211
- end
212
-
213
- it 'should allow false' do
214
- @boat.set(:bool => false)
215
- @boat.should be_valid
216
- end
217
-
218
- it 'should not allow nil' do
219
- @boat.set(:bool => nil)
220
- @boat.should_not be_valid
221
- @boat.errors.on(:bool).should include('Bool must not be nil')
222
- end
223
- end
224
-
225
- describe 'for non-nullable ParanoidBoolean properties' do
226
- before do
227
- @boat = HasNotNullableParanoidBoolean.new(:id => 1)
228
- end
229
-
230
- it 'should allow true' do
231
- @boat.set(:bool => true)
232
- @boat.should be_valid
233
- end
234
-
235
- it 'should allow false' do
236
- @boat.set(:bool => false)
237
- @boat.should be_valid
238
- end
239
-
240
- it 'should not allow nil' do
241
- @boat.set(:bool => nil)
242
- @boat.should_not be_valid
243
- @boat.errors.on(:bool).should include('Bool must not be nil')
244
- end
245
- end
246
-
247
- { :float => Float, :big_decimal => BigDecimal }.each do |column, type|
248
- describe "for #{type} properties" do
249
- before do
250
- @boat = SailBoat.new(:id => 1)
251
- end
252
-
253
- it 'should allow integers' do
254
- @boat.set(column => 1)
255
- @boat.should be_valid
256
- end
257
-
258
- it 'should allow floats' do
259
- @boat.set(column => '1.0')
260
- @boat.should be_valid
261
- end
262
-
263
- it 'should allow decimals' do
264
- @boat.set(column => BigDecimal('1'))
265
- @boat.should be_valid
266
- end
267
- end
268
- end
269
-
270
- describe 'for within validator' do
271
- before :all do
272
- class ::LimitedBoat
273
- include DataMapper::Resource
274
- property :id, Integer, :serial => true
275
- property :limited, String, :set => ['foo', 'bar', 'bang'], :default => 'foo'
276
- end
277
- end
278
-
279
- before do
280
- @boat = LimitedBoat.new
281
- end
282
-
283
- it 'should set default value' do
284
- @boat.should be_valid
285
- end
286
-
287
- it 'should not accept value not in range' do
288
- @boat.limited = "blah"
289
- @boat.should_not be_valid
290
- @boat.errors.on(:limited).should include('Limited must be one of [foo, bar, bang]')
291
- end
292
-
293
- end
294
-
295
- describe 'for custom messages' do
296
- it "should have correct error message" do
297
- custom_boat = Class.new do
298
- include DataMapper::Resource
299
- property :id, Integer, :serial => true
300
- property :name, String, :nullable => false, :message => "This boat must have name"
301
- end
302
- boat = custom_boat.new
303
- boat.should_not be_valid
304
- boat.errors.on(:name).should include('This boat must have name')
305
- end
306
-
307
- it "should have correct error messages" do
308
- custom_boat = Class.new do
309
- include DataMapper::Resource
310
- property :id, Integer, :serial => true
311
- property :name, String, :nullable => false, :length => 5..20, :format => /^[a-z]+$/,
312
- :messages => {
313
- :presence => "This boat must have name",
314
- :length => "Name must have at least 4 and at most 20 chars",
315
- :format => "Please use only small letters"
316
- }
317
- end
318
-
319
- boat = custom_boat.new
320
- boat.should_not be_valid
321
- boat.errors.on(:name).should include("This boat must have name")
322
- boat.errors.on(:name).should include("Name must have at least 4 and at most 20 chars")
323
- boat.errors.on(:name).should include("Please use only small letters")
324
-
325
- boat.name = "%%"
326
- boat.should_not be_valid
327
- boat.errors.on(:name).should_not include("This boat must have name")
328
- boat.errors.on(:name).should include("Name must have at least 4 and at most 20 chars")
329
- boat.errors.on(:name).should include("Please use only small letters")
330
-
331
- boat.name = "%%asd"
332
- boat.should_not be_valid
333
- boat.errors.on(:name).should_not include("This boat must have name")
334
- boat.errors.on(:name).should_not include("Name must have at least 4 and at most 20 chars")
335
- boat.errors.on(:name).should include("Please use only small letters")
336
-
337
- boat.name = "superboat"
338
- boat.should be_valid
339
- boat.errors.on(:name).should be_nil
340
- end
341
- end
342
- end