dm-validations 0.9.11 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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