Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

including patch by teamon for [#472 state:resolved]

  • Loading branch information...
commit 3888768bcec19500fa17c45451a668063473db60 1 parent d88cfe9
Adam French authored
62 dm-validations/lib/dm-validations/auto_validate.rb
... ... @@ -1,6 +1,29 @@
1 1 module DataMapper
  2 + class Property
  3 + # for options_with_message
  4 + PROPERTY_OPTIONS << :message << :messages
  5 + end
  6 +
2 7 module Validate
3 8 module AutoValidate
  9 + # adds message for validator
  10 + def options_with_message(base_options, property, validator_name)
  11 + options = base_options.clone
  12 + opts = property.options
  13 + options[:message] = if opts[:messages]
  14 + if opts[:messages].is_a?(Hash) and msg = opts[:messages][validator_name]
  15 + msg
  16 + else
  17 + nil
  18 + end
  19 + elsif opts[:message]
  20 + opts[:message]
  21 + else
  22 + nil
  23 + end
  24 + options
  25 + end
  26 +
4 27
5 28 ##
6 29 # Auto-generate validations for a given property. This will only occur
@@ -33,6 +56,21 @@ module AutoValidate
33 56 # Using a Integer type causes a validates_is_number
34 57 # validator to be created for the property. integer_only
35 58 # is set to false, and precision/scale match the property
  59 + #
  60 + #
  61 + # Messages
  62 + #
  63 + # :messages => {..}
  64 + # Setting :messages hash replaces standard error messages
  65 + # with custom ones. For instance:
  66 + # :messages => {:presence => "Field is required",
  67 + # :format => "Field has invalid format"}
  68 + # Hash keys are: :presence, :format, :length, :is_unique,
  69 + # :is_number, :is_primitive
  70 + #
  71 + # :message => "Some message"
  72 + # It is just shortcut if only one validation option is set
  73 + #
36 74 def auto_generate_validations(property)
37 75 property.options[:auto_validation] = true unless property.options.has_key?(:auto_validation)
38 76 return unless property.options[:auto_validation]
@@ -44,7 +82,8 @@ def auto_generate_validations(property)
44 82
45 83 # presence
46 84 unless opts[:allow_nil]
47   - validates_present property.name, opts
  85 + # validates_present property.name, opts
  86 + validates_present property.name, options_with_message(opts, property, :presence)
48 87 end
49 88
50 89 # length
@@ -56,39 +95,46 @@ def auto_generate_validations(property)
56 95 else
57 96 opts[:maximum] = len
58 97 end
59   - validates_length property.name, opts
  98 + # validates_length property.name, opts
  99 + validates_length property.name, options_with_message(opts, property, :length)
60 100 end
61 101
62 102 # format
63 103 if property.options.has_key?(:format)
64 104 opts[:with] = property.options[:format]
65   - validates_format property.name, opts
  105 + # validates_format property.name, opts
  106 + validates_format property.name, options_with_message(opts, property, :format)
66 107 end
67 108
68 109 # uniqueness validator
69 110 if property.options.has_key?(:unique)
70 111 value = property.options[:unique]
71 112 if value.is_a?(Array) || value.is_a?(Symbol)
72   - validates_is_unique property.name, :scope => Array(value)
  113 + # validates_is_unique property.name, :scope => Array(value)
  114 + validates_is_unique property.name, options_with_message({:scope => Array(value)}, property, :is_unique)
73 115 elsif value.is_a?(TrueClass)
74   - validates_is_unique property.name
  116 + # validates_is_unique property.name
  117 + validates_is_unique property.name, options_with_message({}, property, :is_unique)
75 118 end
76 119 end
77 120
78 121 # numeric validator
79 122 if Integer == property.type
80 123 opts[:integer_only] = true
81   - validates_is_number property.name, opts
  124 + # validates_is_number property.name, opts
  125 + validates_is_number property.name, options_with_message(opts, property, :is_number)
82 126 elsif BigDecimal == property.type || Float == property.type
83 127 opts[:precision] = property.precision
84 128 opts[:scale] = property.scale
85   - validates_is_number property.name, opts
  129 + # validates_is_number property.name, opts
  130 + validates_is_number property.name, options_with_message(opts, property, :is_number)
86 131 else
87 132 # We only need this in the case we don't already
88 133 # have a numeric validator, because otherwise
89 134 # it will cause duplicate validation errors
90 135 unless property.custom?
91   - validates_is_primitive property.name, opts
  136 + # validates_is_primitive property.name, opts
  137 + validates_is_primitive property.name, options_with_message(opts, property, :is_primitive)
92 138 end
93 139 end
94 140 end
49 dm-validations/spec/integration/auto_validate_spec.rb
@@ -259,4 +259,53 @@ class HasNotNullableParanoidBoolean
259 259 end
260 260 end
261 261 end
  262 +
  263 + describe 'for custom messages' do
  264 + it "should have correct error message" do
  265 + custom_boat = Class.new do
  266 + include DataMapper::Resource
  267 + property :id, Integer, :serial => true
  268 + property :name, String, :nullable => false, :message => "This boat must have name"
  269 + end
  270 + boat = custom_boat.new
  271 + boat.should_not be_valid
  272 +
  273 + boat.errors.on(:name).should eql(["This boat must have name"])
  274 + end
  275 +
  276 + it "should have correct error messages" do
  277 + custom_boat = Class.new do
  278 + include DataMapper::Resource
  279 + property :id, Integer, :serial => true
  280 + property :name, String, :nullable => false, :length => 5..20, :format => /^[a-z]+$/,
  281 + :messages => {
  282 + :presence => "This boat must have name",
  283 + :length => "Name must have at least 4 and at most 20 chars",
  284 + :format => "Please use only small letters"
  285 + }
  286 + end
  287 +
  288 + boat = custom_boat.new
  289 + boat.should_not be_valid
  290 + boat.errors.on(:name).should include("This boat must have name")
  291 + boat.errors.on(:name).should include("Name must have at least 4 and at most 20 chars")
  292 + boat.errors.on(:name).should include("Please use only small letters")
  293 +
  294 + boat.name = "%%"
  295 + boat.should_not be_valid
  296 + boat.errors.on(:name).should_not include("This boat must have name")
  297 + boat.errors.on(:name).should include("Name must have at least 4 and at most 20 chars")
  298 + boat.errors.on(:name).should include("Please use only small letters")
  299 +
  300 + boat.name = "%%asd"
  301 + boat.should_not be_valid
  302 + boat.errors.on(:name).should_not include("This boat must have name")
  303 + boat.errors.on(:name).should_not include("Name must have at least 4 and at most 20 chars")
  304 + boat.errors.on(:name).should include("Please use only small letters")
  305 +
  306 + boat.name = "superboat"
  307 + boat.should be_valid
  308 + boat.errors.on(:name).should be_nil
  309 + end
  310 + end
262 311 end

0 comments on commit 3888768

Please sign in to comment.
Something went wrong with that request. Please try again.