diff options
Diffstat (limited to 'activemodel/lib')
-rw-r--r-- | activemodel/lib/active_model/errors.rb | 69 | ||||
-rw-r--r-- | activemodel/lib/active_model/secure_password.rb | 8 | ||||
-rw-r--r-- | activemodel/lib/active_model/serialization.rb | 4 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations.rb | 6 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations/inclusion.rb | 23 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations/validates.rb | 11 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations/with.rb | 12 |
7 files changed, 98 insertions, 35 deletions
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 0dc10e3c7d..5e3cf510b0 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -60,9 +60,13 @@ module ActiveModel # p.validate! # => ["can not be nil"] # p.errors.full_messages # => ["name can not be nil"] # # etc.. - class Errors < ActiveSupport::OrderedHash + class Errors + include Enumerable + CALLBACKS_OPTIONS = [:if, :unless, :on, :allow_nil, :allow_blank] + attr_reader :messages + # Pass in the instance of the object that is using the errors object. # # class Person @@ -71,12 +75,29 @@ module ActiveModel # end # end def initialize(base) - @base = base - super() + @base = base + @messages = ActiveSupport::OrderedHash.new end - alias_method :get, :[] - alias_method :set, :[]= + # Clear the messages + def clear + messages.clear + end + + # Do the error messages include an error with key +error+? + def include?(error) + messages.include? error + end + + # Get messages for +key+ + def get(key) + messages[key] + end + + # Set messages for +key+ to +value+ + def set(key, value) + messages[key] = value + end # When passed a symbol or a name of a method, returns an array of errors # for the method. @@ -110,7 +131,7 @@ module ActiveModel # # then yield :name and "must be specified" # end def each - each_key do |attribute| + messages.each_key do |attribute| self[attribute].each { |error| yield attribute, error } end end @@ -125,6 +146,16 @@ module ActiveModel values.flatten.size end + # Returns all message values + def values + messages.values + end + + # Returns all message keys + def keys + messages.keys + end + # Returns an array of error messages, with the attribute name included # # p.errors.add(:name, "can't be blank") @@ -169,9 +200,7 @@ module ActiveModel end def to_hash - hash = ActiveSupport::OrderedHash.new - each { |k, v| (hash[k] ||= []) << v } - hash + messages.dup end # Adds +message+ to the error messages on +attribute+, which will be returned on a call to @@ -221,26 +250,20 @@ module ActiveModel # company.errors.full_messages # => # ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Address can't be blank"] def full_messages - full_messages = [] - - each do |attribute, messages| - messages = Array.wrap(messages) - next if messages.empty? - + map { |attribute, message| if attribute == :base - messages.each {|m| full_messages << m } + message else attr_name = attribute.to_s.gsub('.', '_').humanize attr_name = @base.class.human_attribute_name(attribute, :default => attr_name) - options = { :default => "%{attribute} %{message}", :attribute => attr_name } - messages.each do |m| - full_messages << I18n.t(:"errors.format", options.merge(:message => m)) - end + I18n.t(:"errors.format", { + :default => "%{attribute} %{message}", + :attribute => attr_name, + :message => message + }) end - end - - full_messages + } end # Translates an error message in its default scope diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 7e8370a04c..957d0ddaaa 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -33,12 +33,16 @@ module ActiveModel attr_reader :password attr_accessor :password_confirmation - attr_protected(:password_digest) if respond_to?(:attr_protected) - validates_confirmation_of :password validates_presence_of :password_digest include InstanceMethodsOnActivation + + if respond_to?(:attributes_protected_by_default) + def self.attributes_protected_by_default + super + ['password_digest'] + end + end end end diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index f659419293..caf44a2ee0 100644 --- a/activemodel/lib/active_model/serialization.rb +++ b/activemodel/lib/active_model/serialization.rb @@ -15,7 +15,7 @@ module ActiveModel # attr_accessor :name # # def attributes - # @attributes ||= {'name' => nil} + # {'name' => name} # end # # end @@ -45,7 +45,7 @@ module ActiveModel # attr_accessor :name # # def attributes - # @attributes ||= {'name' => nil} + # {'name' => name} # end # # end diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index cdf23c7b1b..efd071fedc 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -146,8 +146,10 @@ module ActiveModel end # List all validators that being used to validate a specific attribute. - def validators_on(attribute) - _validators[attribute.to_sym] + def validators_on(*attributes) + attributes.map do |attribute| + _validators[attribute.to_sym] + end.flatten end # Check if method is an attribute method or not. diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 049b093618..108586b8df 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -8,9 +8,26 @@ module ActiveModel ":in option of the configuration hash" unless options[:in].respond_to?(:include?) end - def validate_each(record, attribute, value) - unless options[:in].include?(value) - record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) + # On Ruby 1.9 Range#include? checks all possible values in the range for equality, + # so it may be slow for large ranges. The new Range#cover? uses the previous logic + # of comparing a value with the range endpoints. + if (1..2).respond_to?(:cover?) + def validate_each(record, attribute, value) + included = if options[:in].is_a?(Range) + options[:in].cover?(value) + else + options[:in].include?(value) + end + + unless included + record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) + end + end + else + def validate_each(record, attribute, value) + unless options[:in].include?(value) + record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value)) + end end end end diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb index 0132f68282..7ff42de00b 100644 --- a/activemodel/lib/active_model/validations/validates.rb +++ b/activemodel/lib/active_model/validations/validates.rb @@ -81,10 +81,9 @@ module ActiveModel # def validates(*attributes) defaults = attributes.extract_options! - validations = defaults.slice!(:if, :unless, :on, :allow_blank, :allow_nil) + validations = defaults.slice!(*_validates_default_keys) raise ArgumentError, "You need to supply at least one attribute" if attributes.empty? - raise ArgumentError, "Attribute names must be symbols" if attributes.any?{ |attribute| !attribute.is_a?(Symbol) } raise ArgumentError, "You need to supply at least one validation" if validations.empty? defaults.merge!(:attributes => attributes) @@ -104,6 +103,12 @@ module ActiveModel protected + # When creating custom validators, it might be useful to be able to specify + # additional default keys. This can be done by overwriting this method. + def _validates_default_keys + [ :if, :unless, :on, :allow_blank, :allow_nil ] + end + def _parse_validates_options(options) #:nodoc: case options when TrueClass @@ -118,4 +123,4 @@ module ActiveModel end end end -end
\ No newline at end of file +end diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 200efd4eb5..1663697727 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -8,6 +8,18 @@ module ActiveModel end end + class WithValidator < EachValidator + def validate_each(record, attr, val) + method_name = options[:with] + + if record.method(method_name).arity == 0 + record.send method_name + else + record.send method_name, attr + end + end + end + module ClassMethods # Passes the record off to the class or classes specified and allows them # to add errors based on more complex conditions. |