From f7862b2c34b5b298bf7b937c55f0637ebfe43a25 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 12 May 2010 00:18:42 -0300 Subject: Refactor of active_model/naming.rb and allow collection and element to be writable Signed-off-by: Jeremy Kemper --- activemodel/lib/active_model/naming.rb | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index 8cdd3d2fe8..a860388bae 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -3,18 +3,36 @@ require 'active_support/inflector' module ActiveModel class Name < String - attr_reader :singular, :plural, :element, :collection, :partial_path - alias_method :cache_key, :collection + attr_reader :singular, :plural, :element def initialize(klass) super(klass.name) @klass = klass @singular = ActiveSupport::Inflector.underscore(self).tr('/', '_').freeze @plural = ActiveSupport::Inflector.pluralize(@singular).freeze - @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze + @collection = nil + self.element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze + end + + def element=(element) + @element = element @human = ActiveSupport::Inflector.humanize(@element).freeze - @collection = ActiveSupport::Inflector.tableize(self).freeze - @partial_path = "#{@collection}/#{@element}".freeze + @default_collection = nil + @partial_path = nil + end + + def collection + @collection || default_collection + end + alias_method :cache_key, :collection + + def collection=(collection) + @collection = collection + @partial_path = nil + end + + def partial_path + @partial_path ||= "#{collection}/#{@element}" end # Transform the model name into a more humane format, using I18n. By default, @@ -34,6 +52,12 @@ module ActiveModel options.reverse_merge! :scope => [@klass.i18n_scope, :models], :count => 1, :default => defaults I18n.translate(defaults.shift, options) end + + private + + def default_collection + @default_collection ||= ActiveSupport::Inflector.tableize(self.sub(/[^:]*$/, @element)).freeze + end end # ActiveModel::Naming is a module that creates a +model_name+ method on your -- cgit v1.2.3 From bea3c26833ad3e1e94f7331e0553a4e2164e7de5 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 6 May 2010 12:35:08 -0300 Subject: Make ActiveResource serialize XML correctly when element_name is set. [#4529] Signed-off-by: Jeremy Kemper --- activemodel/lib/active_model/serializers/xml.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb index df7026b3ec..934af2b8a8 100644 --- a/activemodel/lib/active_model/serializers/xml.rb +++ b/activemodel/lib/active_model/serializers/xml.rb @@ -90,7 +90,7 @@ module ActiveModel @builder = options[:builder] @builder.instruct! unless options[:skip_instruct] - root = (options[:root] || @serializable.class.model_name.singular).to_s + root = (options[:root] || @serializable.class.model_name.element).to_s root = ActiveSupport::XmlMini.rename_key(root, options) args = [root] -- cgit v1.2.3 From 6334006b815eadd83575fe6d00e9010838530ee7 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 12 May 2010 14:29:39 -0300 Subject: Revert "Refactor of active_model/naming.rb and allow collection and element to be writable" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit f7862b2c34b5b298bf7b937c55f0637ebfe43a25. Signed-off-by: José Valim --- activemodel/lib/active_model/naming.rb | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb index a860388bae..8cdd3d2fe8 100644 --- a/activemodel/lib/active_model/naming.rb +++ b/activemodel/lib/active_model/naming.rb @@ -3,36 +3,18 @@ require 'active_support/inflector' module ActiveModel class Name < String - attr_reader :singular, :plural, :element + attr_reader :singular, :plural, :element, :collection, :partial_path + alias_method :cache_key, :collection def initialize(klass) super(klass.name) @klass = klass @singular = ActiveSupport::Inflector.underscore(self).tr('/', '_').freeze @plural = ActiveSupport::Inflector.pluralize(@singular).freeze - @collection = nil - self.element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze - end - - def element=(element) - @element = element + @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).freeze @human = ActiveSupport::Inflector.humanize(@element).freeze - @default_collection = nil - @partial_path = nil - end - - def collection - @collection || default_collection - end - alias_method :cache_key, :collection - - def collection=(collection) - @collection = collection - @partial_path = nil - end - - def partial_path - @partial_path ||= "#{collection}/#{@element}" + @collection = ActiveSupport::Inflector.tableize(self).freeze + @partial_path = "#{@collection}/#{@element}".freeze end # Transform the model name into a more humane format, using I18n. By default, @@ -52,12 +34,6 @@ module ActiveModel options.reverse_merge! :scope => [@klass.i18n_scope, :models], :count => 1, :default => defaults I18n.translate(defaults.shift, options) end - - private - - def default_collection - @default_collection ||= ActiveSupport::Inflector.tableize(self.sub(/[^:]*$/, @element)).freeze - end end # ActiveModel::Naming is a module that creates a +model_name+ method on your -- cgit v1.2.3 From 9131a88bb8e82f139ec49b4057fb6065ba0a2c6a Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Tue, 11 May 2010 12:28:42 +0200 Subject: validation macros can now be used within an instance --- activemodel/lib/active_model/validations.rb | 9 +-- .../lib/active_model/validations/acceptance.rb | 2 +- .../lib/active_model/validations/confirmation.rb | 2 +- .../lib/active_model/validations/exclusion.rb | 2 +- activemodel/lib/active_model/validations/format.rb | 2 +- .../lib/active_model/validations/helper_methods.rb | 12 ++++ .../lib/active_model/validations/inclusion.rb | 2 +- activemodel/lib/active_model/validations/length.rb | 2 +- .../lib/active_model/validations/numericality.rb | 2 +- .../lib/active_model/validations/presence.rb | 2 +- activemodel/lib/active_model/validations/with.rb | 66 ++++++++++++++++++++++ 11 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 activemodel/lib/active_model/validations/helper_methods.rb (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 7c705b8899..1e2901633e 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -46,6 +46,9 @@ module ActiveModel included do extend ActiveModel::Translation + + extend HelperMethods; include HelperMethods + define_callbacks :validate, :scope => :name attr_accessor :validation_context @@ -138,12 +141,6 @@ module ActiveModel def attribute_method?(attribute) method_defined?(attribute) end - private - - def _merge_attributes(attr_names) - options = attr_names.extract_options! - options.merge(:attributes => attr_names.flatten) - end end # Returns the Errors object that holds all information about attribute error messages. diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index fbd622eb6d..26b12b504b 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -21,7 +21,7 @@ module ActiveModel end end - module ClassMethods + module HelperMethods # Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example: # # class Person < ActiveRecord::Base diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index 8041d4b61f..51445343f2 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -12,7 +12,7 @@ module ActiveModel end end - module ClassMethods + module HelperMethods # Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example: # # Model: diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index 2f51edfa9a..2ee78f5dd2 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -12,7 +12,7 @@ module ActiveModel end end - module ClassMethods + module HelperMethods # Validates that the value of the specified attribute is not in a particular enumerable object. # # class Person < ActiveRecord::Base diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index 9a9e7eca4d..c34c860d4d 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -24,7 +24,7 @@ module ActiveModel end end - module ClassMethods + module HelperMethods # Validates whether the value of the specified attribute is of the correct form, going by the regular expression provided. # You can require that the attribute matches the regular expression: # diff --git a/activemodel/lib/active_model/validations/helper_methods.rb b/activemodel/lib/active_model/validations/helper_methods.rb new file mode 100644 index 0000000000..4c709b1fa9 --- /dev/null +++ b/activemodel/lib/active_model/validations/helper_methods.rb @@ -0,0 +1,12 @@ +module ActiveModel + module Validations + module HelperMethods + private + + def _merge_attributes(attr_names) + options = attr_names.extract_options! + options.merge(:attributes => attr_names.flatten) + end + end + end +end \ No newline at end of file diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 96dc8b6e15..446646d247 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -12,7 +12,7 @@ module ActiveModel end end - module ClassMethods + module HelperMethods # Validates whether the value of the specified attribute is available in a particular enumerable object. # # class Person < ActiveRecord::Base diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index 95da3e93ea..d7218f4f52 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -51,7 +51,7 @@ module ActiveModel end end - module ClassMethods + module HelperMethods # Validates that the specified attribute matches the length restrictions supplied. Only one option can be used at a time: # diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index f974999bef..716010e88b 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -70,7 +70,7 @@ module ActiveModel end - module ClassMethods + module HelperMethods # Validates whether the value of the specified attribute is numeric by trying to convert it to # a float with Kernel.Float (if only_integer is false) or applying it to the regular expression # /\A[\+\-]?\d+\Z/ (if only_integer is set to true). diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index 4a71cf79b5..b319f4834b 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -8,7 +8,7 @@ module ActiveModel end end - module ClassMethods + module HelperMethods # Validates that the specified attributes are not blank (as defined by Object#blank?). Happens by default on save. Example: # # class Person < ActiveRecord::Base diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 83d3ea80d6..2a2d0d55b4 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -75,5 +75,71 @@ module ActiveModel end end end + + # Passes the record off to the class or classes specified and allows them + # to add errors based on more complex conditions. + # + # class Person + # include ActiveModel::Validations + # + # validates :instance_validations + # + # def instance_validations + # validates_with MyValidator + # end + # end + # + # class MyValidator < ActiveModel::Validator + # def validate(record) + # if some_complex_logic + # record.errors[:base] << "This record is invalid" + # end + # end + # + # private + # def some_complex_logic + # # ... + # end + # end + # + # You may also pass it multiple classes, like so: + # + # class Person + # include ActiveModel::Validations + # + # validates :instance_validations, :on => :create + # + # def instance_validations + # validates_with MyValidator, MyOtherValidator + # end + # end + # + # Standard configuration options (:on, :if and :unless), which are + # available on the class version of validates_with, should instead be + # placed on the validates method as these are applied and tested + # in the callback + # + # If you pass any additional configuration options, they will be passed + # to the class and available as options: + # + # class Person + # include ActiveModel::Validations + # validates_with MyValidator, :my_custom_key => "my custom value" + # end + # + # class MyValidator < ActiveModel::Validator + # def validate(record) + # options[:my_custom_key] # => "my custom value" + # end + # end + # + def validates_with(*args, &block) + options = args.extract_options! + args.each do |klass| + validator = klass.new(options, &block) + validator.setup(self) if validator.respond_to?(:setup) + validator.validate(self) + end + end end end \ No newline at end of file -- cgit v1.2.3 From 92160219a8bf17bd435252304319c094e56e5849 Mon Sep 17 00:00:00 2001 From: Josh Kalderimis Date: Tue, 11 May 2010 15:36:09 +0200 Subject: =?UTF-8?q?minor=20changes=20to=20instance=20level=20validations?= =?UTF-8?q?=20implementation=20based=20on=20feedback=20from=20Jos=C3=A9=20?= =?UTF-8?q?Valim?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- activemodel/lib/active_model/validations.rb | 3 +- .../lib/active_model/validations/helper_methods.rb | 12 ------- activemodel/lib/active_model/validations/with.rb | 37 +++++++--------------- activemodel/lib/active_model/validator.rb | 3 ++ 4 files changed, 17 insertions(+), 38 deletions(-) delete mode 100644 activemodel/lib/active_model/validations/helper_methods.rb (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb index 1e2901633e..f472f50f9b 100644 --- a/activemodel/lib/active_model/validations.rb +++ b/activemodel/lib/active_model/validations.rb @@ -47,7 +47,8 @@ module ActiveModel included do extend ActiveModel::Translation - extend HelperMethods; include HelperMethods + extend HelperMethods + include HelperMethods define_callbacks :validate, :scope => :name diff --git a/activemodel/lib/active_model/validations/helper_methods.rb b/activemodel/lib/active_model/validations/helper_methods.rb deleted file mode 100644 index 4c709b1fa9..0000000000 --- a/activemodel/lib/active_model/validations/helper_methods.rb +++ /dev/null @@ -1,12 +0,0 @@ -module ActiveModel - module Validations - module HelperMethods - private - - def _merge_attributes(attr_names) - options = attr_names.extract_options! - options.merge(:attributes => attr_names.flatten) - end - end - end -end \ No newline at end of file diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb index 2a2d0d55b4..6dbde5bfad 100644 --- a/activemodel/lib/active_model/validations/with.rb +++ b/activemodel/lib/active_model/validations/with.rb @@ -1,5 +1,13 @@ module ActiveModel module Validations + module HelperMethods + private + def _merge_attributes(attr_names) + options = attr_names.extract_options! + options.merge(:attributes => attr_names.flatten) + end + end + module ClassMethods # Passes the record off to the class or classes specified and allows them @@ -89,18 +97,8 @@ module ActiveModel # end # end # - # class MyValidator < ActiveModel::Validator - # def validate(record) - # if some_complex_logic - # record.errors[:base] << "This record is invalid" - # end - # end - # - # private - # def some_complex_logic - # # ... - # end - # end + # Please consult the class method documentation for more information on + # creating your own validator. # # You may also pass it multiple classes, like so: # @@ -120,24 +118,13 @@ module ActiveModel # in the callback # # If you pass any additional configuration options, they will be passed - # to the class and available as options: - # - # class Person - # include ActiveModel::Validations - # validates_with MyValidator, :my_custom_key => "my custom value" - # end - # - # class MyValidator < ActiveModel::Validator - # def validate(record) - # options[:my_custom_key] # => "my custom value" - # end - # end + # to the class and available as options, please refer to the + # class version of this method for more information # def validates_with(*args, &block) options = args.extract_options! args.each do |klass| validator = klass.new(options, &block) - validator.setup(self) if validator.respond_to?(:setup) validator.validate(self) end end diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb index 906d239bcc..56179c1a6c 100644 --- a/activemodel/lib/active_model/validator.rb +++ b/activemodel/lib/active_model/validator.rb @@ -88,6 +88,9 @@ module ActiveModel #:nodoc: # klass.send :attr_accessor, :custom_attribute # end # end + # + # This setup method is only called when used with validation macros or the + # class level validates_with method. # class Validator attr_reader :options -- cgit v1.2.3 From bc1c8d58ec45593acba614d1d0fecb49adef08ff Mon Sep 17 00:00:00 2001 From: Jeroen van Dijk Date: Sat, 15 May 2010 19:43:45 +0200 Subject: Make ActiveModel::Errors#add_on_blank and #add_on_empty accept an options hash and make various Validators pass their (filtered) options. This makes it possible to pass additional options through Validators to message generation. E.g. plugin authors want to add validates_presence_of :foo, :format => "some format". Also, cleanup the :default vs :message options confusion in ActiveModel validation message generation. Also, deprecate ActiveModel::Errors#add_on_blank(attributes, custom_message) in favor of ActiveModel::Errors#add_on_blank(attributes, options). Original patch by Sven Fuchs, some minor changes and has been changed to be applicable to master again [#4057 state:committed] Signed-off-by: Jeremy Kemper --- activemodel/lib/active_model/errors.rb | 54 ++++++++++++++++------ .../lib/active_model/validations/acceptance.rb | 2 +- .../lib/active_model/validations/confirmation.rb | 2 +- .../lib/active_model/validations/exclusion.rb | 2 +- activemodel/lib/active_model/validations/format.rb | 4 +- .../lib/active_model/validations/inclusion.rb | 2 +- activemodel/lib/active_model/validations/length.rb | 4 +- .../lib/active_model/validations/numericality.rb | 8 ++-- .../lib/active_model/validations/presence.rb | 2 +- 9 files changed, 54 insertions(+), 26 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 14afc5265f..b18b62f926 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -179,25 +179,45 @@ module ActiveModel # If +message+ is a Proc, it will be called, allowing for things like Time.now to be used within an error def add(attribute, message = nil, options = {}) message ||= :invalid - message = generate_message(attribute, message, options) if message.is_a?(Symbol) + + reserved = [:minimum, :maximum, :is, :within , :in, :allow_nil, :allow_blank, :case_sensitive, + :too_long, :too_short, :wrong_length, :on, :if, :unless , :tokenizer, :invalid, + :only_integer, :odd, :even, :less_than, :with, :accept] + + message = generate_message(attribute, message, options.except(*reserved)) if message.is_a?(Symbol) + message = message.call if message.is_a?(Proc) self[attribute] << message end # Will add an error message to each of the attributes in +attributes+ that is empty. - def add_on_empty(attributes, custom_message = nil) + def add_on_empty(attributes, options = {}) + if options && !options.is_a?(Hash) + options = { :message => options } + ActiveSupport::Deprecation.warn \ + "ActiveModel::Errors#add_on_empty(attributes, custom_message) has been deprecated.\n" + + "Instead of passing a custom_message pass an options Hash { :message => custom_message }." + end + [attributes].flatten.each do |attribute| value = @base.send(:read_attribute_for_validation, attribute) is_empty = value.respond_to?(:empty?) ? value.empty? : false - add(attribute, :empty, :default => custom_message) unless !value.nil? && !is_empty + add(attribute, :empty, options) if value.nil? || is_empty end end # Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?). - def add_on_blank(attributes, custom_message = nil) + def add_on_blank(attributes, options = {}) + if options && !options.is_a?(Hash) + options = { :message => options } + ActiveSupport::Deprecation.warn \ + "ActiveModel::Errors#add_on_blank(attributes, custom_message) has been deprecated.\n" + + "Instead of passing a custom_message pass an options Hash { :message => custom_message }." + end + [attributes].flatten.each do |attribute| value = @base.send(:read_attribute_for_validation, attribute) - add(attribute, :blank, :default => custom_message) if value.blank? + add(attribute, :blank, options) if value.blank? end end @@ -254,18 +274,26 @@ module ActiveModel #
  • errors.attributes.title.blank
  • #
  • errors.messages.blank
  • # - def generate_message(attribute, message = :invalid, options = {}) - message, options[:default] = options[:default], message if options[:default].is_a?(Symbol) + + def generate_message(attribute, type = :invalid, options = {}) + type = options.delete(:message) if options[:message].is_a?(Symbol) + + if options[:default] + ActiveSupport::Deprecation.warn \ + "ActiveModel::Errors#generate_message(attributes, custom_message) has been deprecated.\n" + + "Use ActiveModel::Errors#generate_message(attributes, :message => 'your message') instead." + options[:message] = options.delete(:default) + end defaults = @base.class.lookup_ancestors.map do |klass| - [ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.attributes.#{attribute}.#{message}", - :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.#{message}" ] + [ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.attributes.#{attribute}.#{type}", + :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.#{type}" ] end - defaults << options.delete(:default) - defaults << :"#{@base.class.i18n_scope}.errors.messages.#{message}" - defaults << :"errors.attributes.#{attribute}.#{message}" - defaults << :"errors.messages.#{message}" + defaults << options.delete(:message) + defaults << :"#{@base.class.i18n_scope}.errors.messages.#{type}" + defaults << :"errors.attributes.#{attribute}.#{type}" + defaults << :"errors.messages.#{type}" defaults.compact! defaults.flatten! diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index 26b12b504b..ced083b312 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -7,7 +7,7 @@ module ActiveModel def validate_each(record, attribute, value) unless value == options[:accept] - record.errors.add(attribute, :accepted, :default => options[:message]) + record.errors.add(attribute, :accepted, options) end end diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index 51445343f2..66bce0d2de 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -4,7 +4,7 @@ module ActiveModel def validate_each(record, attribute, value) confirmed = record.send(:"#{attribute}_confirmation") return if confirmed.nil? || value == confirmed - record.errors.add(attribute, :confirmation, :default => options[:message]) + record.errors.add(attribute, :confirmation, options) end def setup(klass) diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index 2ee78f5dd2..da4c84fbd6 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -8,7 +8,7 @@ module ActiveModel def validate_each(record, attribute, value) return unless options[:in].include?(value) - record.errors.add(attribute, :exclusion, :default => options[:message], :value => value) + record.errors.add(attribute, :exclusion, options.merge(:value => value)) end end diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index c34c860d4d..2667baa5a0 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -3,9 +3,9 @@ module ActiveModel class FormatValidator < EachValidator def validate_each(record, attribute, value) if options[:with] && value.to_s !~ options[:with] - record.errors.add(attribute, :invalid, :default => options[:message], :value => value) + record.errors.add(attribute, :invalid, options.merge(:value => value)) elsif options[:without] && value.to_s =~ options[:without] - record.errors.add(attribute, :invalid, :default => options[:message], :value => value) + record.errors.add(attribute, :invalid, options.merge(:value => value)) end end diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 446646d247..0ddf191b4f 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -8,7 +8,7 @@ module ActiveModel def validate_each(record, attribute, value) return if options[:in].include?(value) - record.errors.add(attribute, :inclusion, :default => options[:message], :value => value) + record.errors.add(attribute, :inclusion, options.merge(:value => value)) end end diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index d7218f4f52..9b671f58de 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -37,7 +37,7 @@ module ActiveModel CHECKS.each do |key, validity_check| next unless check_value = options[key] - custom_message = options[:message] || options[MESSAGES[key]] + options[:message] ||= options[MESSAGES[key]] if options[MESSAGES[key]] valid_value = if key == :maximum value.nil? || value.size.send(validity_check, check_value) @@ -46,7 +46,7 @@ module ActiveModel end next if valid_value - record.errors.add(attribute, MESSAGES[key], :default => custom_message, :count => check_value) + record.errors.add(attribute, MESSAGES[key], options.merge(:count => check_value)) end end end diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index 716010e88b..d407258442 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -26,13 +26,13 @@ module ActiveModel return if options[:allow_nil] && raw_value.nil? unless value = parse_raw_value_as_a_number(raw_value) - record.errors.add(attr_name, :not_a_number, :value => raw_value, :default => options[:message]) + record.errors.add(attr_name, :not_a_number, options.merge(:value => raw_value)) return end if options[:only_integer] unless value = parse_raw_value_as_an_integer(raw_value) - record.errors.add(attr_name, :not_an_integer, :value => raw_value, :default => options[:message]) + record.errors.add(attr_name, :not_an_integer, options.merge(:value => raw_value)) return end end @@ -41,14 +41,14 @@ module ActiveModel case option when :odd, :even unless value.to_i.send(CHECKS[option]) - record.errors.add(attr_name, option, :value => value, :default => options[:message]) + record.errors.add(attr_name, option, options.merge(:value => value)) end else option_value = option_value.call(record) if option_value.is_a?(Proc) option_value = record.send(option_value) if option_value.is_a?(Symbol) unless value.send(CHECKS[option], option_value) - record.errors.add(attr_name, option, :default => options[:message], :value => value, :count => option_value) + record.errors.add(attr_name, option, options.merge(:value => value, :count => option_value)) end end end diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index b319f4834b..2826a10ffe 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -4,7 +4,7 @@ module ActiveModel module Validations class PresenceValidator < EachValidator def validate(record) - record.errors.add_on_blank(attributes, options[:message]) + record.errors.add_on_blank(attributes, options) end end -- cgit v1.2.3 From d6cbb27e7b260c970bf7d07dc0b0591ed82cee2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 15 May 2010 21:55:16 +0200 Subject: Revert "Make ActiveModel::Errors#add_on_blank and #add_on_empty accept an options hash and make various Validators pass their (filtered) options." Having a huge array to whitelist options is not the proper way to handle this case. This means that the ActiveModel::Errors object should know about the options given in *all* validators and break the extensibility added by the validators itself. If the intent is to whitelist options before sending them to I18n, each validator should clean its respective options instead of throwing the responsibility to the Errors object. This reverts commit bc1c8d58ec45593acba614d1d0fecb49adef08ff. --- activemodel/lib/active_model/errors.rb | 54 ++++++---------------- .../lib/active_model/validations/acceptance.rb | 2 +- .../lib/active_model/validations/confirmation.rb | 2 +- .../lib/active_model/validations/exclusion.rb | 2 +- activemodel/lib/active_model/validations/format.rb | 4 +- .../lib/active_model/validations/inclusion.rb | 2 +- activemodel/lib/active_model/validations/length.rb | 4 +- .../lib/active_model/validations/numericality.rb | 8 ++-- .../lib/active_model/validations/presence.rb | 2 +- 9 files changed, 26 insertions(+), 54 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index b18b62f926..14afc5265f 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -179,45 +179,25 @@ module ActiveModel # If +message+ is a Proc, it will be called, allowing for things like Time.now to be used within an error def add(attribute, message = nil, options = {}) message ||= :invalid - - reserved = [:minimum, :maximum, :is, :within , :in, :allow_nil, :allow_blank, :case_sensitive, - :too_long, :too_short, :wrong_length, :on, :if, :unless , :tokenizer, :invalid, - :only_integer, :odd, :even, :less_than, :with, :accept] - - message = generate_message(attribute, message, options.except(*reserved)) if message.is_a?(Symbol) - + message = generate_message(attribute, message, options) if message.is_a?(Symbol) message = message.call if message.is_a?(Proc) self[attribute] << message end # Will add an error message to each of the attributes in +attributes+ that is empty. - def add_on_empty(attributes, options = {}) - if options && !options.is_a?(Hash) - options = { :message => options } - ActiveSupport::Deprecation.warn \ - "ActiveModel::Errors#add_on_empty(attributes, custom_message) has been deprecated.\n" + - "Instead of passing a custom_message pass an options Hash { :message => custom_message }." - end - + def add_on_empty(attributes, custom_message = nil) [attributes].flatten.each do |attribute| value = @base.send(:read_attribute_for_validation, attribute) is_empty = value.respond_to?(:empty?) ? value.empty? : false - add(attribute, :empty, options) if value.nil? || is_empty + add(attribute, :empty, :default => custom_message) unless !value.nil? && !is_empty end end # Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?). - def add_on_blank(attributes, options = {}) - if options && !options.is_a?(Hash) - options = { :message => options } - ActiveSupport::Deprecation.warn \ - "ActiveModel::Errors#add_on_blank(attributes, custom_message) has been deprecated.\n" + - "Instead of passing a custom_message pass an options Hash { :message => custom_message }." - end - + def add_on_blank(attributes, custom_message = nil) [attributes].flatten.each do |attribute| value = @base.send(:read_attribute_for_validation, attribute) - add(attribute, :blank, options) if value.blank? + add(attribute, :blank, :default => custom_message) if value.blank? end end @@ -274,26 +254,18 @@ module ActiveModel #
  • errors.attributes.title.blank
  • #
  • errors.messages.blank
  • # - - def generate_message(attribute, type = :invalid, options = {}) - type = options.delete(:message) if options[:message].is_a?(Symbol) - - if options[:default] - ActiveSupport::Deprecation.warn \ - "ActiveModel::Errors#generate_message(attributes, custom_message) has been deprecated.\n" + - "Use ActiveModel::Errors#generate_message(attributes, :message => 'your message') instead." - options[:message] = options.delete(:default) - end + def generate_message(attribute, message = :invalid, options = {}) + message, options[:default] = options[:default], message if options[:default].is_a?(Symbol) defaults = @base.class.lookup_ancestors.map do |klass| - [ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.attributes.#{attribute}.#{type}", - :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.#{type}" ] + [ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.attributes.#{attribute}.#{message}", + :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.underscore}.#{message}" ] end - defaults << options.delete(:message) - defaults << :"#{@base.class.i18n_scope}.errors.messages.#{type}" - defaults << :"errors.attributes.#{attribute}.#{type}" - defaults << :"errors.messages.#{type}" + defaults << options.delete(:default) + defaults << :"#{@base.class.i18n_scope}.errors.messages.#{message}" + defaults << :"errors.attributes.#{attribute}.#{message}" + defaults << :"errors.messages.#{message}" defaults.compact! defaults.flatten! diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb index ced083b312..26b12b504b 100644 --- a/activemodel/lib/active_model/validations/acceptance.rb +++ b/activemodel/lib/active_model/validations/acceptance.rb @@ -7,7 +7,7 @@ module ActiveModel def validate_each(record, attribute, value) unless value == options[:accept] - record.errors.add(attribute, :accepted, options) + record.errors.add(attribute, :accepted, :default => options[:message]) end end diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb index 66bce0d2de..51445343f2 100644 --- a/activemodel/lib/active_model/validations/confirmation.rb +++ b/activemodel/lib/active_model/validations/confirmation.rb @@ -4,7 +4,7 @@ module ActiveModel def validate_each(record, attribute, value) confirmed = record.send(:"#{attribute}_confirmation") return if confirmed.nil? || value == confirmed - record.errors.add(attribute, :confirmation, options) + record.errors.add(attribute, :confirmation, :default => options[:message]) end def setup(klass) diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index da4c84fbd6..2ee78f5dd2 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -8,7 +8,7 @@ module ActiveModel def validate_each(record, attribute, value) return unless options[:in].include?(value) - record.errors.add(attribute, :exclusion, options.merge(:value => value)) + record.errors.add(attribute, :exclusion, :default => options[:message], :value => value) end end diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb index 2667baa5a0..c34c860d4d 100644 --- a/activemodel/lib/active_model/validations/format.rb +++ b/activemodel/lib/active_model/validations/format.rb @@ -3,9 +3,9 @@ module ActiveModel class FormatValidator < EachValidator def validate_each(record, attribute, value) if options[:with] && value.to_s !~ options[:with] - record.errors.add(attribute, :invalid, options.merge(:value => value)) + record.errors.add(attribute, :invalid, :default => options[:message], :value => value) elsif options[:without] && value.to_s =~ options[:without] - record.errors.add(attribute, :invalid, options.merge(:value => value)) + record.errors.add(attribute, :invalid, :default => options[:message], :value => value) end end diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index 0ddf191b4f..446646d247 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -8,7 +8,7 @@ module ActiveModel def validate_each(record, attribute, value) return if options[:in].include?(value) - record.errors.add(attribute, :inclusion, options.merge(:value => value)) + record.errors.add(attribute, :inclusion, :default => options[:message], :value => value) end end diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb index 9b671f58de..d7218f4f52 100644 --- a/activemodel/lib/active_model/validations/length.rb +++ b/activemodel/lib/active_model/validations/length.rb @@ -37,7 +37,7 @@ module ActiveModel CHECKS.each do |key, validity_check| next unless check_value = options[key] - options[:message] ||= options[MESSAGES[key]] if options[MESSAGES[key]] + custom_message = options[:message] || options[MESSAGES[key]] valid_value = if key == :maximum value.nil? || value.size.send(validity_check, check_value) @@ -46,7 +46,7 @@ module ActiveModel end next if valid_value - record.errors.add(attribute, MESSAGES[key], options.merge(:count => check_value)) + record.errors.add(attribute, MESSAGES[key], :default => custom_message, :count => check_value) end end end diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb index d407258442..716010e88b 100644 --- a/activemodel/lib/active_model/validations/numericality.rb +++ b/activemodel/lib/active_model/validations/numericality.rb @@ -26,13 +26,13 @@ module ActiveModel return if options[:allow_nil] && raw_value.nil? unless value = parse_raw_value_as_a_number(raw_value) - record.errors.add(attr_name, :not_a_number, options.merge(:value => raw_value)) + record.errors.add(attr_name, :not_a_number, :value => raw_value, :default => options[:message]) return end if options[:only_integer] unless value = parse_raw_value_as_an_integer(raw_value) - record.errors.add(attr_name, :not_an_integer, options.merge(:value => raw_value)) + record.errors.add(attr_name, :not_an_integer, :value => raw_value, :default => options[:message]) return end end @@ -41,14 +41,14 @@ module ActiveModel case option when :odd, :even unless value.to_i.send(CHECKS[option]) - record.errors.add(attr_name, option, options.merge(:value => value)) + record.errors.add(attr_name, option, :value => value, :default => options[:message]) end else option_value = option_value.call(record) if option_value.is_a?(Proc) option_value = record.send(option_value) if option_value.is_a?(Symbol) unless value.send(CHECKS[option], option_value) - record.errors.add(attr_name, option, options.merge(:value => value, :count => option_value)) + record.errors.add(attr_name, option, :default => options[:message], :value => value, :count => option_value) end end end diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb index 2826a10ffe..b319f4834b 100644 --- a/activemodel/lib/active_model/validations/presence.rb +++ b/activemodel/lib/active_model/validations/presence.rb @@ -4,7 +4,7 @@ module ActiveModel module Validations class PresenceValidator < EachValidator def validate(record) - record.errors.add_on_blank(attributes, options) + record.errors.add_on_blank(attributes, options[:message]) end end -- cgit v1.2.3 From 6b4e0cc526f55b5532cf99292c94f0a4db53b16f Mon Sep 17 00:00:00 2001 From: Federico Brubacher Date: Sun, 16 May 2010 07:24:41 -0300 Subject: a cloned object no longer mimics changed flags from creator , plus a test case [#4614 state:resolved] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- activemodel/lib/active_model/dirty.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb index a7ee15a7f6..bbcc345e4b 100644 --- a/activemodel/lib/active_model/dirty.rb +++ b/activemodel/lib/active_model/dirty.rb @@ -124,11 +124,12 @@ module ActiveModel @previously_changed end + # Map of change attr => original value. + def changed_attributes + @changed_attributes ||= {} + end + private - # Map of change attr => original value. - def changed_attributes - @changed_attributes ||= {} - end # Handle *_changed? for +method_missing+. def attribute_changed?(attr) -- cgit v1.2.3