aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/MIT-LICENSE21
-rwxr-xr-xactivemodel/Rakefile31
-rw-r--r--activemodel/activemodel.gemspec19
-rw-r--r--activemodel/examples/validations.rb2
-rw-r--r--activemodel/lib/active_model.rb2
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb2
-rw-r--r--activemodel/lib/active_model/dirty.rb14
-rw-r--r--activemodel/lib/active_model/errors.rb5
-rw-r--r--activemodel/lib/active_model/lint.rb95
-rw-r--r--activemodel/lib/active_model/observing.rb17
-rw-r--r--activemodel/lib/active_model/validations.rb18
-rw-r--r--activemodel/lib/active_model/validations/numericality.rb21
-rw-r--r--activemodel/lib/active_model/validations/presence.rb2
-rw-r--r--activemodel/lib/active_model/validations/with.rb2
-rw-r--r--activemodel/lib/active_model/validations_repair_helper.rb41
-rw-r--r--activemodel/lib/active_model/version.rb9
-rw-r--r--activemodel/lib/activemodel.rb1
-rw-r--r--activemodel/test/cases/lint_test.rb50
-rw-r--r--activemodel/test/cases/naming_test.rb2
-rw-r--r--activemodel/test/cases/observing_test.rb1
-rw-r--r--activemodel/test/cases/serializeration/json_serialization_test.rb4
-rw-r--r--activemodel/test/cases/serializeration/xml_serialization_test.rb4
-rw-r--r--activemodel/test/cases/validations/i18n_generate_message_validation_test.rb10
-rw-r--r--activemodel/test/cases/validations/i18n_validation_test.rb59
-rw-r--r--activemodel/test/cases/validations/numericality_validation_test.rb18
-rw-r--r--activemodel/test/cases/validations/presence_validation_test.rb1
-rw-r--r--activemodel/test/cases/validations/with_validation_test.rb2
-rw-r--r--activemodel/test/cases/validations_test.rb22
-rw-r--r--activemodel/test/models/reply.rb6
29 files changed, 348 insertions, 133 deletions
diff --git a/activemodel/MIT-LICENSE b/activemodel/MIT-LICENSE
new file mode 100644
index 0000000000..e7accc5ea1
--- /dev/null
+++ b/activemodel/MIT-LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2004-2009 David Heinemeier Hansson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/activemodel/Rakefile b/activemodel/Rakefile
index ae2fbdb002..fd69a557aa 100755
--- a/activemodel/Rakefile
+++ b/activemodel/Rakefile
@@ -1,7 +1,13 @@
-#!/usr/bin/env ruby
-require 'rake'
+require File.join(File.dirname(__FILE__), 'lib', 'active_model', 'version')
+
+PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
+PKG_NAME = 'activemodel'
+PKG_VERSION = ActiveModel::VERSION::STRING + PKG_BUILD
+PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
+RELEASE_NAME = "REL #{PKG_VERSION}"
+
+
require 'rake/testtask'
-require 'rake/rdoctask'
task :default => :test
@@ -9,14 +15,19 @@ Rake::TestTask.new do |t|
t.libs << "test"
t.test_files = Dir.glob("test/cases/**/*_test.rb").sort
t.verbose = true
+ t.warning = true
end
+
task :isolated_test do
ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
Dir.glob("test/**/*_test.rb").all? do |file|
- system(ruby, '-Ilib:test', file)
+ system(ruby, '-w', '-Ilib:test', file)
end or raise "Failures"
end
+
+require 'rake/rdoctask'
+
# Generate the RDoc documentation
Rake::RDocTask.new do |rdoc|
rdoc.rdoc_dir = 'doc'
@@ -27,3 +38,15 @@ Rake::RDocTask.new do |rdoc|
rdoc.rdoc_files.include('README', 'CHANGES')
rdoc.rdoc_files.include('lib/**/*.rb')
end
+
+
+require 'rake/packagetask'
+require 'rake/gempackagetask'
+
+spec = eval(File.read('activemodel.gemspec'))
+
+Rake::GemPackageTask.new(spec) do |p|
+ p.gem_spec = spec
+ p.need_tar = true
+ p.need_zip = true
+end
diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec
new file mode 100644
index 0000000000..c3ff624419
--- /dev/null
+++ b/activemodel/activemodel.gemspec
@@ -0,0 +1,19 @@
+Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = 'activemodel'
+ s.version = '3.0.pre'
+ s.summary = "A toolkit for building other modeling frameworks like ActiveRecord"
+ s.description = %q{Extracts common modeling concerns from ActiveRecord to share between similar frameworks like ActiveResource.}
+
+ s.author = "David Heinemeier Hansson"
+ s.email = "david@loudthinking.com"
+ s.rubyforge_project = "activemodel"
+ s.homepage = "http://www.rubyonrails.org"
+
+ s.has_rdoc = true
+
+ s.add_dependency('activesupport', '= 3.0.pre')
+
+ s.require_path = 'lib'
+ s.files = Dir["CHANGELOG", "MIT-LICENSE", "README", "lib/**/*"]
+end
diff --git a/activemodel/examples/validations.rb b/activemodel/examples/validations.rb
index 3f8311ff96..b039897ea5 100644
--- a/activemodel/examples/validations.rb
+++ b/activemodel/examples/validations.rb
@@ -1,4 +1,4 @@
-require 'activemodel'
+require 'active_model'
class Person
include ActiveModel::Conversion
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index 244f3a546e..67f529262d 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -31,6 +31,7 @@ module ActiveModel
autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods'
autoload :Dirty, 'active_model/dirty'
autoload :Errors, 'active_model/errors'
+ autoload :Lint, 'active_model/lint'
autoload :Name, 'active_model/naming'
autoload :Naming, 'active_model/naming'
autoload :Observer, 'active_model/observing'
@@ -40,6 +41,7 @@ module ActiveModel
autoload :TestCase, 'active_model/test_case'
autoload :Validations, 'active_model/validations'
autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper'
+ autoload :VERSION, 'active_model/version'
module Serializers
autoload :JSON, 'active_model/serializers/json'
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index 1091ad3095..aa35a2726e 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -181,7 +181,7 @@ module ActiveModel
end
def attribute_methods_generated?
- @attribute_methods_generated ? true : false
+ @attribute_methods_generated ||= nil
end
protected
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index 624c3647ca..735c61df74 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -72,12 +72,26 @@ module ActiveModel
changed.inject({}) { |h, attr| h[attr] = attribute_change(attr); h }
end
+ # Map of attributes that were changed when the model was saved.
+ # person.name # => 'bob'
+ # person.name = 'robert'
+ # person.save
+ # person.previous_changes # => {'name' => ['bob, 'robert']}
+ def previous_changes
+ previously_changed_attributes
+ end
+
private
# Map of change <tt>attr => original value</tt>.
def changed_attributes
@changed_attributes ||= {}
end
+ # Map of fields that were changed when the model was saved
+ def previously_changed_attributes
+ @previously_changed || {}
+ end
+
# Handle <tt>*_changed?</tt> for +method_missing+.
def attribute_changed?(attr)
changed_attributes.include?(attr)
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 7a3001174f..7a48960f89 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -1,7 +1,8 @@
require 'active_support/core_ext/string/inflections'
+require 'active_support/ordered_hash'
module ActiveModel
- class Errors < Hash
+ class Errors < ActiveSupport::OrderedHash
include DeprecatedErrorMethods
def initialize(base)
@@ -113,7 +114,7 @@ module ActiveModel
full_messages
end
- # Translates an error message in it's default scope (<tt>activemodel.errrors.messages</tt>).
+ # Translates an error message in its default scope (<tt>activemodel.errors.messages</tt>).
# Error messages are first looked up in <tt>models.MODEL.attributes.ATTRIBUTE.MESSAGE</tt>, if it's not there,
# it's looked up in <tt>models.MODEL.MESSAGE</tt> and if that is not there it returns the translation of the
# default message (e.g. <tt>activemodel.errors.messages.MESSAGE</tt>). The translated model name,
diff --git a/activemodel/lib/active_model/lint.rb b/activemodel/lib/active_model/lint.rb
new file mode 100644
index 0000000000..ceaa29dc8c
--- /dev/null
+++ b/activemodel/lib/active_model/lint.rb
@@ -0,0 +1,95 @@
+# You can test whether an object is compliant with the ActiveModel API by
+# calling ActiveModel::Lint.test(object). It will emit a Test::Unit
+# output that tells you whether your object is fully compliant, or if not,
+# which aspects of the API are not implemented.
+#
+# These tests do not attempt to determine the semantic correctness of the
+# returned values. For instance, you could implement valid? to always
+# return true, and the tests would pass. It is up to you to ensure that
+# the values are semantically meaningful.
+#
+# Objects you pass in are expected to return a compliant object from a
+# call to to_model. It is perfectly fine for to_model to return self.
+module ActiveModel
+ module Lint
+ def self.test(object, verbosity = 2, output = STDOUT)
+ require "test/unit"
+ require "test/unit/ui/console/testrunner"
+
+ test_class = Class.new(::Test::Unit::TestCase) do
+ include Test
+
+ define_method(:setup) do
+ assert object.respond_to?(:to_model), "The object should respond_to :to_model"
+ @object = object.to_model
+ super
+ end
+ end
+
+ ::Test::Unit::UI::Console::TestRunner.new(test_class, verbosity, output).start
+ end
+
+ module Test
+ def assert_boolean(name, result)
+ assert result == true || result == false, "#{name} should be a boolean"
+ end
+
+ # valid?
+ # ------
+ #
+ # Returns a boolean that specifies whether the object is in a valid or invalid
+ # state.
+ def test_valid?
+ assert @object.respond_to?(:valid?), "The model should respond to valid?"
+ assert_boolean "valid?", @object.valid?
+ end
+
+ # new_record?
+ # -----------
+ #
+ # Returns a boolean that specifies whether the object has been persisted yet.
+ # This is used when calculating the URL for an object. If the object is
+ # not persisted, a form for that object, for instance, will be POSTed to the
+ # collection. If it is persisted, a form for the object will put PUTed to the
+ # URL for the object.
+ def test_new_record?
+ assert @object.respond_to?(:new_record?), "The model should respond to new_record?"
+ assert_boolean "new_record?", @object.new_record?
+ end
+
+ def test_destroyed?
+ assert @object.respond_to?(:destroyed?), "The model should respond to destroyed?"
+ assert_boolean "destroyed?", @object.destroyed?
+ end
+
+ # errors
+ # ------
+ #
+ # Returns an object that has :[] and :full_messages defined on it. See below
+ # for more details.
+ def setup
+ assert @object.respond_to?(:errors), "The model should respond to errors"
+ @errors = @object.errors
+ end
+
+ # This module tests the #errors object
+ module Errors
+ # Returns an Array of Strings that are the errors for the attribute in
+ # question. If localization is used, the Strings should be localized
+ # for the current locale. If no error is present, this method should
+ # return an empty Array.
+ def test_errors_aref
+ assert @errors[:hello].is_a?(Array), "errors#[] should return an Array"
+ end
+
+ # Returns an Array of all error messages for the object. Each message
+ # should contain information about the field, if applicable.
+ def test_errors_full_messages
+ assert @errors.full_messages.is_a?(Array), "errors#full_messages should return an Array"
+ end
+ end
+
+ include Errors
+ end
+ end
+end
diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb
index 3b230c43b9..d9d1ab8967 100644
--- a/activemodel/lib/active_model/observing.rb
+++ b/activemodel/lib/active_model/observing.rb
@@ -40,23 +40,6 @@ module ActiveModel
observers.each { |o| instantiate_observer(o) }
end
- # Wraps methods with before and after notifications.
- #
- # wrap_with_notifications :create, :save, :update, :destroy
- def wrap_with_notifications(*methods)
- methods.each do |method|
- class_eval(<<-EOS, __FILE__, __LINE__ + 1)
- def #{method}_with_notifications(*args, &block)
- notify_observers(:before_#{method})
- result = #{method}_without_notifications(*args, &block)
- notify_observers(:after_#{method})
- result
- end
- EOS
- alias_method_chain(method, :notifications)
- end
- end
-
protected
def instantiate_observer(observer) #:nodoc:
# string/symbol
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index 7d49e60790..edeb508a08 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -6,10 +6,10 @@ require 'active_support/callbacks'
module ActiveModel
module Validations
extend ActiveSupport::Concern
- include ActiveSupport::Callbacks
+ include ActiveSupport::NewCallbacks
included do
- define_callbacks :validate
+ define_callbacks :validate, :scope => :name
end
module ClassMethods
@@ -64,7 +64,7 @@ module ActiveModel
attrs = attrs.flatten
# Declare the validation.
- send(validation_method(options[:on]), options) do |record|
+ validate options do |record|
attrs.each do |attr|
value = record.send(:read_attribute_for_validation, attr)
next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
@@ -73,10 +73,14 @@ module ActiveModel
end
end
- private
- def validation_method(on)
- :validate
+ def validate(*args, &block)
+ options = args.last
+ if options.is_a?(Hash) && options.key?(:on)
+ options[:if] = Array(options[:if])
+ options[:if] << "@_on_validate == :#{options[:on]}"
end
+ set_callback(:validate, *args, &block)
+ end
end
# Returns the Errors object that holds all information about attribute error messages.
@@ -87,7 +91,7 @@ module ActiveModel
# Runs all the specified validations and returns true if no errors were added otherwise false.
def valid?
errors.clear
- run_callbacks(:validate)
+ _run_validate_callbacks
errors.empty?
end
diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb
index ada6e28594..32dbcd82d0 100644
--- a/activemodel/lib/active_model/validations/numericality.rb
+++ b/activemodel/lib/active_model/validations/numericality.rb
@@ -31,6 +31,21 @@ module ActiveModel
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value.
+ #
+ # The following checks can also be supplied with a proc or a symbol which corresponds to a method:
+ # * <tt>:greater_than</tt>
+ # * <tt>:greater_than_or_equal_to</tt>
+ # * <tt>:equal_to</tt>
+ # * <tt>:less_than</tt>
+ # * <tt>:less_than_or_equal_to</tt>
+ #
+ # class Person < ActiveRecord::Base
+ # validates_numericality_of :width, :less_than => Proc.new { |person| person.height }
+ # validates_numericality_of :width, :greater_than => :minimum_weight
+ # end
+ #
+ #
+
def validates_numericality_of(*attr_names)
configuration = { :only_integer => false, :allow_nil => false }
configuration.update(attr_names.extract_options!)
@@ -38,7 +53,8 @@ module ActiveModel
numericality_options = ALL_NUMERICALITY_CHECKS.keys & configuration.keys
(numericality_options - [ :odd, :even ]).each do |option|
- raise ArgumentError, ":#{option} must be a number" unless configuration[option].is_a?(Numeric)
+ value = configuration[option]
+ raise ArgumentError, ":#{option} must be a number, a symbol or a proc" unless value.is_a?(Numeric) || value.is_a?(Proc) || value.is_a?(Symbol)
end
validates_each(attr_names,configuration) do |record, attr_name, value|
@@ -74,6 +90,9 @@ module ActiveModel
record.errors.add(attr_name, option, :value => raw_value, :default => configuration[:message])
end
else
+ configuration[option] = configuration[option].call(record) if configuration[option].is_a? Proc
+ configuration[option] = record.method(configuration[option]).call if configuration[option].is_a? Symbol
+
unless raw_value.method(ALL_NUMERICALITY_CHECKS[option])[configuration[option]]
record.errors.add(attr_name, option, :default => configuration[:message], :value => raw_value, :count => configuration[option])
end
diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb
index 72d6b1c6f0..3ff677c137 100644
--- a/activemodel/lib/active_model/validations/presence.rb
+++ b/activemodel/lib/active_model/validations/presence.rb
@@ -32,7 +32,7 @@ module ActiveModel
# can't use validates_each here, because it cannot cope with nonexistent attributes,
# while errors.add_on_empty can
- send(validation_method(configuration[:on]), configuration) do |record|
+ validate configuration do |record|
record.errors.add_on_blank(attr_names, configuration[:message])
end
end
diff --git a/activemodel/lib/active_model/validations/with.rb b/activemodel/lib/active_model/validations/with.rb
index 851cdfebf0..edc2133ddc 100644
--- a/activemodel/lib/active_model/validations/with.rb
+++ b/activemodel/lib/active_model/validations/with.rb
@@ -51,7 +51,7 @@ module ActiveModel
def validates_with(*args)
configuration = args.extract_options!
- send(validation_method(configuration[:on]), configuration) do |record|
+ validate configuration do |record|
args.each do |klass|
klass.new(record, configuration.except(:on, :if, :unless)).validate
end
diff --git a/activemodel/lib/active_model/validations_repair_helper.rb b/activemodel/lib/active_model/validations_repair_helper.rb
index 432e411308..40741e6dbe 100644
--- a/activemodel/lib/active_model/validations_repair_helper.rb
+++ b/activemodel/lib/active_model/validations_repair_helper.rb
@@ -2,43 +2,34 @@ module ActiveModel
module ValidationsRepairHelper
extend ActiveSupport::Concern
- module Toolbox
- def self.record_validations(*model_classes)
- model_classes.inject({}) do |repair, klass|
- repair[klass] ||= {}
- [:validate, :validate_on_create, :validate_on_update].each do |callback|
- the_callback = klass.instance_variable_get("@#{callback.to_s}_callbacks")
- repair[klass][callback] = (the_callback.nil? ? nil : the_callback.dup)
- end
- repair
- end
- end
-
- def self.reset_validations(recorded)
- recorded.each do |klass, repairs|
- [:validate, :validate_on_create, :validate_on_update].each do |callback|
- klass.instance_variable_set("@#{callback.to_s}_callbacks", repairs[callback])
- end
- end
- end
- end
-
module ClassMethods
def repair_validations(*model_classes)
setup do
- @validation_repairs = Toolbox.record_validations(*model_classes)
+ @_stored_callbacks = {}
+ model_classes.each do |k|
+ @_stored_callbacks[k] = k._validate_callbacks.dup
+ end
end
teardown do
- Toolbox.reset_validations(@validation_repairs)
+ model_classes.each do |k|
+ k._validate_callbacks = @_stored_callbacks[k]
+ k.__update_callbacks(:validate)
+ end
end
end
end
def repair_validations(*model_classes, &block)
- validation_repairs = Toolbox.record_validations(*model_classes)
+ @__stored_callbacks = {}
+ model_classes.each do |k|
+ @__stored_callbacks[k] = k._validate_callbacks.dup
+ end
return block.call
ensure
- Toolbox.reset_validations(validation_repairs)
+ model_classes.each do |k|
+ k._validate_callbacks = @__stored_callbacks[k]
+ k.__update_callbacks(:validate)
+ end
end
end
end
diff --git a/activemodel/lib/active_model/version.rb b/activemodel/lib/active_model/version.rb
new file mode 100644
index 0000000000..0c233b7b4f
--- /dev/null
+++ b/activemodel/lib/active_model/version.rb
@@ -0,0 +1,9 @@
+module ActiveModel
+ module VERSION #:nodoc:
+ MAJOR = 3
+ MINOR = 0
+ TINY = "pre"
+
+ STRING = [MAJOR, MINOR, TINY].join('.')
+ end
+end
diff --git a/activemodel/lib/activemodel.rb b/activemodel/lib/activemodel.rb
deleted file mode 100644
index da3133103b..0000000000
--- a/activemodel/lib/activemodel.rb
+++ /dev/null
@@ -1 +0,0 @@
-require 'active_model'
diff --git a/activemodel/test/cases/lint_test.rb b/activemodel/test/cases/lint_test.rb
new file mode 100644
index 0000000000..ed576a91e2
--- /dev/null
+++ b/activemodel/test/cases/lint_test.rb
@@ -0,0 +1,50 @@
+require "cases/helper"
+
+class TestLint < ActiveModel::TestCase
+ class CompliantObject
+ def to_model
+ self
+ end
+
+ def valid?() true end
+ def new_record?() true end
+ def destroyed?() true end
+
+ def errors
+ obj = Object.new
+ def obj.[](key) [] end
+ def obj.full_messages() [] end
+ obj
+ end
+ end
+
+ def assert_output(object, failures, errors, *test_names)
+ ActiveModel::Lint.test(object, 3, output = StringIO.new)
+ regex = %r{#{failures} failures, #{errors} errors}
+ assert_match regex, output.string
+
+ test_names.each do |test_name|
+ assert_match test_name, output.string
+ end
+ end
+
+ def test_valid
+ assert_output(CompliantObject.new, 0, 0, /test_valid/)
+ end
+
+ def test_new_record
+ assert_output(CompliantObject.new, 0, 0, /test_new_record?/)
+ end
+
+ def test_destroyed
+ assert_output(CompliantObject.new, 0, 0, /test_destroyed/)
+ end
+
+ def test_errors_aref
+ assert_output(CompliantObject.new, 0, 0, /test_errors_aref/)
+ end
+
+ def test_errors_full_messages
+ assert_output(CompliantObject.new, 0, 0, /test_errors_aref/)
+ end
+end
diff --git a/activemodel/test/cases/naming_test.rb b/activemodel/test/cases/naming_test.rb
index e75d4541a3..4d97af3d13 100644
--- a/activemodel/test/cases/naming_test.rb
+++ b/activemodel/test/cases/naming_test.rb
@@ -1,6 +1,6 @@
require 'cases/helper'
-class NamingTest < Test::Unit::TestCase
+class NamingTest < ActiveModel::TestCase
def setup
@model_name = ActiveModel::Name.new('Post::TrackBack')
end
diff --git a/activemodel/test/cases/observing_test.rb b/activemodel/test/cases/observing_test.rb
index fbf93c19ef..e23bda0528 100644
--- a/activemodel/test/cases/observing_test.rb
+++ b/activemodel/test/cases/observing_test.rb
@@ -78,6 +78,7 @@ class ObserverTest < ActiveModel::TestCase
def teardown
FooObserver.instance_eval do
+ undef_method :observed_classes
alias_method :observed_classes, :original_observed_classes
end
end
diff --git a/activemodel/test/cases/serializeration/json_serialization_test.rb b/activemodel/test/cases/serializeration/json_serialization_test.rb
index 6227aedc39..81df52fcb9 100644
--- a/activemodel/test/cases/serializeration/json_serialization_test.rb
+++ b/activemodel/test/cases/serializeration/json_serialization_test.rb
@@ -1,12 +1,14 @@
require 'cases/helper'
require 'models/contact'
+require 'active_support/core_ext/object/instance_variables'
class Contact
+ extend ActiveModel::Naming
include ActiveModel::Serializers::JSON
def attributes
instance_values
- end
+ end unless method_defined?(:attributes)
end
class JsonSerializationTest < ActiveModel::TestCase
diff --git a/activemodel/test/cases/serializeration/xml_serialization_test.rb b/activemodel/test/cases/serializeration/xml_serialization_test.rb
index 428e5a6bd1..6340aad531 100644
--- a/activemodel/test/cases/serializeration/xml_serialization_test.rb
+++ b/activemodel/test/cases/serializeration/xml_serialization_test.rb
@@ -1,12 +1,14 @@
require 'cases/helper'
require 'models/contact'
+require 'active_support/core_ext/object/instance_variables'
class Contact
+ extend ActiveModel::Naming
include ActiveModel::Serializers::Xml
def attributes
instance_values
- end
+ end unless method_defined?(:attributes)
end
module Admin
diff --git a/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb b/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb
index 37bba5e95e..443a81c6ac 100644
--- a/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb
+++ b/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb
@@ -3,9 +3,9 @@ require 'cases/tests_database'
require 'models/person'
-class I18nGenerateMessageValidationTest < Test::Unit::TestCase
+class I18nGenerateMessageValidationTest < ActiveModel::TestCase
def setup
- reset_callbacks Person
+ Person.reset_callbacks(:validate)
@person = Person.new
@old_load_path, @old_backend = I18n.load_path, I18n.backend
@@ -45,12 +45,6 @@ class I18nGenerateMessageValidationTest < Test::Unit::TestCase
I18n.backend = @old_backend
end
- def reset_callbacks(*models)
- models.each do |model|
- model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
- end
- end
-
# validates_inclusion_of: generate_message(attr_name, :inclusion, :default => configuration[:message], :value => value)
def test_generate_message_inclusion_with_default_message
assert_equal 'is not included in the list', @person.errors.generate_message(:title, :inclusion, :default => nil, :value => 'title')
diff --git a/activemodel/test/cases/validations/i18n_validation_test.rb b/activemodel/test/cases/validations/i18n_validation_test.rb
index cc68d847a2..fc4f1926b0 100644
--- a/activemodel/test/cases/validations/i18n_validation_test.rb
+++ b/activemodel/test/cases/validations/i18n_validation_test.rb
@@ -7,8 +7,7 @@ class I18nValidationTest < ActiveModel::TestCase
include ActiveModel::TestsDatabase
def setup
- reset_callbacks Person
-
+ Person.reset_callbacks(:validate)
@person = Person.new
@old_load_path, @old_backend = I18n.load_path, I18n.backend
@@ -18,17 +17,11 @@ class I18nValidationTest < ActiveModel::TestCase
end
def teardown
- reset_callbacks Person
+ Person.reset_callbacks(:validate)
I18n.load_path.replace @old_load_path
I18n.backend = @old_backend
end
- def reset_callbacks(*models)
- models.each do |model|
- model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
- end
- end
-
def test_percent_s_interpolation_syntax_in_error_messages_was_deprecated
assert_not_deprecated do
default = "%s interpolation syntax was deprecated"
@@ -107,32 +100,6 @@ class I18nValidationTest < ActiveModel::TestCase
@person.valid?
end
- def test_validates_length_of_within_generates_message_with_title_too_short
- Person.validates_length_of :title, :within => 3..5
- @person.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil})
- @person.valid?
- end
-
- def test_validates_length_of_within_generates_message_with_title_too_short_and_custom_default_message
- Person.validates_length_of :title, :within => 3..5, :too_short => 'custom'
- @person.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => 'custom'})
- @person.valid?
- end
-
- def test_validates_length_of_within_generates_message_with_title_too_long
- Person.validates_length_of :title, :within => 3..5
- @person.title = 'this title is too long'
- @person.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => nil})
- @person.valid?
- end
-
- def test_validates_length_of_within_generates_message_with_title_too_long_and_custom_default_message
- Person.validates_length_of :title, :within => 3..5, :too_long => 'custom'
- @person.title = 'this title is too long'
- @person.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => 'custom'})
- @person.valid?
- end
-
# validates_length_of :within w/ mocha
def test_validates_length_of_within_generates_message_with_title_too_short
@@ -280,7 +247,7 @@ class I18nValidationTest < ActiveModel::TestCase
@person.valid?
end
- def test_validates_numericality_of_odd_generates_message_with_custom_default_message
+ def test_validates_numericality_of_less_than_odd_generates_message_with_custom_default_message
Person.validates_numericality_of :title, :only_integer => true, :less_than => 0, :message => 'custom'
@person.title = 1
@person.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => 'custom'})
@@ -384,24 +351,6 @@ class I18nValidationTest < ActiveModel::TestCase
assert_equal ['global message'], @person.errors[:title]
end
- def test_validates_length_of_is_finds_custom_model_key_translation
- I18n.backend.store_translations 'en', :activemodel => {:errors => {:models => {:person => {:attributes => {:title => {:wrong_length => 'custom message'}}}}}}
- I18n.backend.store_translations 'en', :activemodel => {:errors => {:messages => {:wrong_length => 'global message'}}}
-
- Person.validates_length_of :title, :is => 5
- @person.valid?
- assert_equal ['custom message'], @person.errors[:title]
- end
-
- def test_validates_length_of_is_finds_global_default_translation
- I18n.backend.store_translations 'en', :activemodel => {:errors => {:messages => {:wrong_length => 'global message'}}}
-
- Person.validates_length_of :title, :is => 5
- @person.valid?
- assert_equal ['global message'], @person.errors[:title]
- end
-
-
# validates_format_of w/o mocha
def test_validates_format_of_finds_custom_model_key_translation
@@ -576,4 +525,4 @@ class I18nValidationTest < ActiveModel::TestCase
assert_equal ["I am a custom error"], @person.errors[:title]
end
-end \ No newline at end of file
+end
diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb
index 0af6eb69ce..d3201966dc 100644
--- a/activemodel/test/cases/validations/numericality_validation_test.rb
+++ b/activemodel/test/cases/validations/numericality_validation_test.rb
@@ -106,6 +106,24 @@ class NumericalityValidationTest < ActiveModel::TestCase
valid!([2])
end
+ def test_validates_numericality_with_proc
+ Topic.send(:define_method, :min_approved, lambda { 5 })
+ Topic.validates_numericality_of :approved, :greater_than_or_equal_to => Proc.new {|topic| topic.min_approved }
+
+ invalid!([3, 4])
+ valid!([5, 6])
+ Topic.send(:remove_method, :min_approved)
+ end
+
+ def test_validates_numericality_with_symbol
+ Topic.send(:define_method, :max_approved, lambda { 5 })
+ Topic.validates_numericality_of :approved, :less_than_or_equal_to => :max_approved
+
+ invalid!([6])
+ valid!([4, 5])
+ Topic.send(:remove_method, :max_approved)
+ end
+
def test_validates_numericality_with_numeric_message
Topic.validates_numericality_of :approved, :less_than => 4, :message => "smaller than {{count}}"
topic = Topic.new("title" => "numeric test", "approved" => 10)
diff --git a/activemodel/test/cases/validations/presence_validation_test.rb b/activemodel/test/cases/validations/presence_validation_test.rb
index bb6fb91774..90b0951a77 100644
--- a/activemodel/test/cases/validations/presence_validation_test.rb
+++ b/activemodel/test/cases/validations/presence_validation_test.rb
@@ -5,6 +5,7 @@ require 'cases/tests_database'
require 'models/topic'
require 'models/developer'
require 'models/person'
+require 'models/custom_reader'
class PresenceValidationTest < ActiveModel::TestCase
include ActiveModel::TestsDatabase
diff --git a/activemodel/test/cases/validations/with_validation_test.rb b/activemodel/test/cases/validations/with_validation_test.rb
index f55fdc5864..c290b49a28 100644
--- a/activemodel/test/cases/validations/with_validation_test.rb
+++ b/activemodel/test/cases/validations/with_validation_test.rb
@@ -1,9 +1,11 @@
# encoding: utf-8
require 'cases/helper'
+require 'cases/tests_database'
require 'models/topic'
class ValidatesWithTest < ActiveRecord::TestCase
+ include ActiveModel::TestsDatabase
include ActiveModel::ValidationsRepairHelper
repair_validations(Topic)
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index 0b340e68bf..78565177d8 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -121,8 +121,8 @@ class ValidationsTest < ActiveModel::TestCase
end
def test_invalid_validator
- Topic.validate 3
- assert_raise(ArgumentError) { t = Topic.create }
+ Topic.validate :i_dont_exist
+ assert_raise(NameError) { t = Topic.create }
end
def test_errors_to_xml
@@ -141,6 +141,22 @@ class ValidationsTest < ActiveModel::TestCase
t = Topic.new("title" => "")
assert !t.valid?
assert_equal "can't be blank", t.errors["title"].first
+ Topic.validates_presence_of :title, :author_name
+ Topic.validate {|topic| topic.errors.add('author_email_address', 'will never be valid')}
+ Topic.validates_length_of :title, :content, :minimum => 2
+
+ t = Topic.new :title => ''
+ assert !t.valid?
+
+ assert_equal :title, key = t.errors.keys.first
+ assert_equal "can't be blank", t.errors[key].first
+ assert_equal 'is too short (minimum is 2 characters)', t.errors[key].second
+ assert_equal :author_name, key = t.errors.keys.second
+ assert_equal "can't be blank", t.errors[key].first
+ assert_equal :author_email_address, key = t.errors.keys.third
+ assert_equal 'will never be valid', t.errors[key].first
+ assert_equal :content, key = t.errors.keys.fourth
+ assert_equal 'is too short (minimum is 2 characters)', t.errors[key].first
end
def test_invalid_should_be_the_opposite_of_valid
@@ -189,4 +205,4 @@ class ValidationsTest < ActiveModel::TestCase
all_errors = t.errors.to_a
assert_deprecated { assert_equal all_errors, t.errors.each_full{|err| err} }
end
-end \ No newline at end of file
+end
diff --git a/activemodel/test/models/reply.rb b/activemodel/test/models/reply.rb
index acfd801674..e86692677f 100644
--- a/activemodel/test/models/reply.rb
+++ b/activemodel/test/models/reply.rb
@@ -2,11 +2,11 @@ require 'models/topic'
class Reply < Topic
validate :errors_on_empty_content
- validate_on_create :title_is_wrong_create
+ validate :title_is_wrong_create, :on => :create
validate :check_empty_title
- validate_on_create :check_content_mismatch
- validate_on_update :check_wrong_update
+ validate :check_content_mismatch, :on => :create
+ validate :check_wrong_update, :on => :update
attr_accessible :title, :author_name, :author_email_address, :written_on, :content, :last_read