aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/lib/active_model/dirty.rb9
-rw-r--r--activemodel/lib/active_model/serializers/xml.rb2
-rw-r--r--activemodel/lib/active_model/validations.rb10
-rw-r--r--activemodel/lib/active_model/validations/acceptance.rb2
-rw-r--r--activemodel/lib/active_model/validations/confirmation.rb2
-rw-r--r--activemodel/lib/active_model/validations/exclusion.rb2
-rw-r--r--activemodel/lib/active_model/validations/format.rb2
-rw-r--r--activemodel/lib/active_model/validations/inclusion.rb2
-rw-r--r--activemodel/lib/active_model/validations/length.rb2
-rw-r--r--activemodel/lib/active_model/validations/numericality.rb2
-rw-r--r--activemodel/lib/active_model/validations/presence.rb2
-rw-r--r--activemodel/lib/active_model/validations/with.rb53
-rw-r--r--activemodel/lib/active_model/validator.rb3
-rw-r--r--activemodel/test/cases/serializeration/xml_serialization_test.rb4
-rw-r--r--activemodel/test/cases/validations/validates_test.rb4
-rw-r--r--activemodel/test/cases/validations_test.rb15
-rw-r--r--activemodel/test/models/automobile.rb12
17 files changed, 104 insertions, 24 deletions
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 <tt>attr => original value</tt>.
+ def changed_attributes
+ @changed_attributes ||= {}
+ end
+
private
- # Map of change <tt>attr => original value</tt>.
- def changed_attributes
- @changed_attributes ||= {}
- end
# Handle <tt>*_changed?</tt> for +method_missing+.
def attribute_changed?(attr)
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]
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 7c705b8899..f472f50f9b 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -46,6 +46,10 @@ module ActiveModel
included do
extend ActiveModel::Translation
+
+ extend HelperMethods
+ include HelperMethods
+
define_callbacks :validate, :scope => :name
attr_accessor :validation_context
@@ -138,12 +142,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/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 <tt>only_integer</tt> is false) or applying it to the regular expression
# <tt>/\A[\+\-]?\d+\Z/</tt> (if <tt>only_integer</tt> 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..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
@@ -75,5 +83,50 @@ 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
+ #
+ # Please consult the class method documentation for more information on
+ # creating your own validator.
+ #
+ # 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 <tt>validates</tt> 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 <tt>options</tt>, 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.validate(self)
+ end
+ end
end
end \ No newline at end of file
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 <tt>validates_with</tt> method.
#
class Validator
attr_reader :options
diff --git a/activemodel/test/cases/serializeration/xml_serialization_test.rb b/activemodel/test/cases/serializeration/xml_serialization_test.rb
index 3ba826a8d0..4e8e4efa25 100644
--- a/activemodel/test/cases/serializeration/xml_serialization_test.rb
+++ b/activemodel/test/cases/serializeration/xml_serialization_test.rb
@@ -37,8 +37,8 @@ class XmlSerializationTest < ActiveModel::TestCase
test "should serialize namespaced root" do
@xml = Admin::Contact.new(@contact.attributes).to_xml
- assert_match %r{^<admin-contact>}, @xml
- assert_match %r{</admin-contact>$}, @xml
+ assert_match %r{^<contact>}, @xml
+ assert_match %r{</contact>$}, @xml
end
test "should serialize default root with namespace" do
diff --git a/activemodel/test/cases/validations/validates_test.rb b/activemodel/test/cases/validations/validates_test.rb
index d15fb4a524..b85e491a9c 100644
--- a/activemodel/test/cases/validations/validates_test.rb
+++ b/activemodel/test/cases/validations/validates_test.rb
@@ -45,7 +45,7 @@ class ValidatesTest < ActiveModel::TestCase
Person.validates :karma, :presence => true, :email => true, :if => :condition_is_true
person = Person.new
person.valid?
- assert ["can't be blank", "is not an email"], person.errors[:karma].sort
+ assert_equal ["can't be blank", "is not an email"], person.errors[:karma].sort
end
def test_validates_with_unless_shared_conditions
@@ -111,4 +111,4 @@ class ValidatesTest < ActiveModel::TestCase
person.valid?
assert_equal ['Local validator please'], person.errors[:title]
end
-end \ No newline at end of file
+end
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index 578ffc27dd..af195af080 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -4,6 +4,7 @@ require 'cases/helper'
require 'models/topic'
require 'models/reply'
require 'models/custom_reader'
+require 'models/automobile'
class ValidationsTest < ActiveModel::TestCase
@@ -227,7 +228,7 @@ class ValidationsTest < ActiveModel::TestCase
t = Topic.new
assert t.invalid?
- assert ["NO BLANKS HERE"], t.errors[:title]
+ assert_equal ["NO BLANKS HERE"], t.errors[:title]
end
def test_list_of_validators_for_model
@@ -252,4 +253,16 @@ class ValidationsTest < ActiveModel::TestCase
Topic.validates_length_of :title, :minimum => 10
assert_equal 10, Topic.validators_on(:title).first.options[:minimum]
end
+
+ def test_validations_on_the_instance_level
+ auto = Automobile.new
+
+ assert auto.invalid?
+ assert_equal 2, auto.errors.size
+
+ auto.make = 'Toyota'
+ auto.model = 'Corolla'
+
+ assert auto.valid?
+ end
end
diff --git a/activemodel/test/models/automobile.rb b/activemodel/test/models/automobile.rb
new file mode 100644
index 0000000000..021ea61c80
--- /dev/null
+++ b/activemodel/test/models/automobile.rb
@@ -0,0 +1,12 @@
+class Automobile
+ include ActiveModel::Validations
+
+ validate :validations
+
+ attr_accessor :make, :model
+
+ def validations
+ validates_presence_of :make
+ validates_length_of :model, :within => 2..10
+ end
+end \ No newline at end of file