aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/CHANGELOG.md16
-rw-r--r--activemodel/MIT-LICENSE2
-rw-r--r--activemodel/activemodel.gemspec2
-rw-r--r--activemodel/lib/active_model.rb2
-rw-r--r--activemodel/lib/active_model/callbacks.rb3
-rw-r--r--activemodel/lib/active_model/conversion.rb6
-rw-r--r--activemodel/lib/active_model/dirty.rb29
-rw-r--r--activemodel/lib/active_model/errors.rb4
-rw-r--r--activemodel/lib/active_model/gem_version.rb2
-rw-r--r--activemodel/lib/active_model/naming.rb2
-rw-r--r--activemodel/lib/active_model/secure_password.rb2
-rw-r--r--activemodel/lib/active_model/serializers/xml.rb2
-rw-r--r--activemodel/lib/active_model/validations/absence.rb2
-rw-r--r--activemodel/lib/active_model/validations/callbacks.rb5
-rw-r--r--activemodel/lib/active_model/validator.rb2
-rw-r--r--activemodel/lib/active_model/version.rb2
-rw-r--r--activemodel/test/cases/callbacks_test.rb16
-rw-r--r--activemodel/test/cases/dirty_test.rb17
-rw-r--r--activemodel/test/cases/validations/callbacks_test.rb20
-rw-r--r--activemodel/test/cases/validations_test.rb5
20 files changed, 72 insertions, 69 deletions
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index b86e988841..f86b4804c8 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1 +1,17 @@
+* Remove deprecated `ActiveModel::Dirty#reset_#{attribute}` and
+ `ActiveModel::Dirty#reset_changes`.
+
+ *Rafael Mendonça França*
+
+* Change the way in which callback chains can be halted.
+
+ The preferred method to halt a callback chain from now on is to explicitly
+ `throw(:abort)`.
+ In the past, returning `false` in an ActiveModel or ActiveModel::Validations
+ `before_` callback had the side effect of halting the callback chain.
+ This is not recommended anymore and, depending on the value of the
+ `config.active_support.halt_callback_chains_on_return_false` option, will
+ either not work at all or display a deprecation warning.
+
+
Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/activemodel/CHANGELOG.md) for previous changes.
diff --git a/activemodel/MIT-LICENSE b/activemodel/MIT-LICENSE
index d58dd9ed9b..3ec7a617cf 100644
--- a/activemodel/MIT-LICENSE
+++ b/activemodel/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2014 David Heinemeier Hansson
+Copyright (c) 2004-2015 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec
index 73600b83fb..3c6eb56296 100644
--- a/activemodel/activemodel.gemspec
+++ b/activemodel/activemodel.gemspec
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
s.summary = 'A toolkit for building modeling frameworks (part of Rails).'
s.description = 'A toolkit for building modeling frameworks like Active Record. Rich support for attributes, callbacks, validations, serialization, internationalization, and testing.'
- s.required_ruby_version = '>= 2.1.0'
+ s.required_ruby_version = '>= 2.2.0'
s.license = 'MIT'
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index feb3d9371d..46d60db756 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2014 David Heinemeier Hansson
+# Copyright (c) 2004-2015 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/activemodel/lib/active_model/callbacks.rb b/activemodel/lib/active_model/callbacks.rb
index b3d70dc515..6214802074 100644
--- a/activemodel/lib/active_model/callbacks.rb
+++ b/activemodel/lib/active_model/callbacks.rb
@@ -6,7 +6,7 @@ module ActiveModel
# Provides an interface for any class to have Active Record like callbacks.
#
# Like the Active Record methods, the callback chain is aborted as soon as
- # one of the methods in the chain returns +false+.
+ # one of the methods throws +:abort+.
#
# First, extend ActiveModel::Callbacks from the class you are creating:
#
@@ -103,7 +103,6 @@ module ActiveModel
def define_model_callbacks(*callbacks)
options = callbacks.extract_options!
options = {
- terminator: ->(_,result) { result == false },
skip_after_callbacks_if_terminated: true,
scope: [:kind, :name],
only: [:before, :around, :after]
diff --git a/activemodel/lib/active_model/conversion.rb b/activemodel/lib/active_model/conversion.rb
index 9c9b6f4a77..9de6ea65be 100644
--- a/activemodel/lib/active_model/conversion.rb
+++ b/activemodel/lib/active_model/conversion.rb
@@ -22,7 +22,7 @@ module ActiveModel
module Conversion
extend ActiveSupport::Concern
- # If your object is already designed to implement all of the Active Model
+ # If your object is already designed to implement all of the \Active \Model
# you can use the default <tt>:to_model</tt> implementation, which simply
# returns +self+.
#
@@ -33,9 +33,9 @@ module ActiveModel
# person = Person.new
# person.to_model == person # => true
#
- # If your model does not act like an Active Model object, then you should
+ # If your model does not act like an \Active \Model object, then you should
# define <tt>:to_model</tt> yourself returning a proxy object that wraps
- # your object with Active Model compliant methods.
+ # your object with \Active \Model compliant methods.
def to_model
self
end
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index 60af31cca7..afba9bab0d 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -1,6 +1,5 @@
require 'active_support/hash_with_indifferent_access'
require 'active_support/core_ext/object/duplicable'
-require 'active_support/core_ext/string/filters'
module ActiveModel
# == Active \Model \Dirty
@@ -102,7 +101,7 @@ module ActiveModel
#
# If an attribute is modified in-place then make use of
# +[attribute_name]_will_change!+ to mark that the attribute is changing.
- # Otherwise Active Model can't track changes to in-place attributes. Note
+ # Otherwise \Active \Model can't track changes to in-place attributes. Note
# that Active Record can detect in-place modifications automatically. You do
# not need to call +[attribute_name]_will_change!+ on Active Record models.
#
@@ -116,7 +115,6 @@ module ActiveModel
included do
attribute_method_suffix '_changed?', '_change', '_will_change!', '_was'
- attribute_method_affix prefix: 'reset_', suffix: '!'
attribute_method_affix prefix: 'restore_', suffix: '!'
end
@@ -170,7 +168,7 @@ module ActiveModel
# Handle <tt>*_changed?</tt> for +method_missing+.
def attribute_changed?(attr, options = {}) #:nodoc:
- result = changed_attributes.include?(attr)
+ result = changes_include?(attr)
result &&= options[:to] == __send__(attr) if options.key?(:to)
result &&= options[:from] == changed_attributes[attr] if options.key?(:from)
result
@@ -188,6 +186,10 @@ module ActiveModel
private
+ def changes_include?(attr_name)
+ attributes_changed_by_setter.include?(attr_name)
+ end
+
# Removes current changes and makes them accessible through +previous_changes+.
def changes_applied # :doc:
@previously_changed = changes
@@ -200,15 +202,6 @@ module ActiveModel
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
end
- def reset_changes
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- `#reset_changes` is deprecated and will be removed on Rails 5.
- Please use `#clear_changes_information` instead.
- MSG
-
- clear_changes_information
- end
-
# Handle <tt>*_change</tt> for +method_missing+.
def attribute_change(attr)
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
@@ -227,16 +220,6 @@ module ActiveModel
set_attribute_was(attr, value)
end
- # Handle <tt>reset_*!</tt> for +method_missing+.
- def reset_attribute!(attr)
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- `#reset_#{attr}!` is deprecated and will be removed on Rails 5.
- Please use `#restore_#{attr}!` instead.
- MSG
-
- restore_attribute!(attr)
- end
-
# Handle <tt>restore_*!</tt> for +method_missing+.
def restore_attribute!(attr)
if attribute_changed?(attr)
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 9105ef5dd6..55687cb3c7 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -283,9 +283,9 @@ module ActiveModel
# ActiveModel::StrictValidationFailed instead of adding the error.
# <tt>:strict</tt> option can also be set to any other exception.
#
- # person.errors.add(:name, nil, strict: true)
+ # person.errors.add(:name, :invalid, strict: true)
# # => ActiveModel::StrictValidationFailed: name is invalid
- # person.errors.add(:name, nil, strict: NameIsInvalid)
+ # person.errors.add(:name, :invalid, strict: NameIsInvalid)
# # => NameIsInvalid: name is invalid
#
# person.errors.messages # => {}
diff --git a/activemodel/lib/active_model/gem_version.rb b/activemodel/lib/active_model/gem_version.rb
index 2403242ce6..762f4fe939 100644
--- a/activemodel/lib/active_model/gem_version.rb
+++ b/activemodel/lib/active_model/gem_version.rb
@@ -1,5 +1,5 @@
module ActiveModel
- # Returns the version of the currently loaded Active Model as a <tt>Gem::Version</tt>
+ # Returns the version of the currently loaded \Active \Model as a <tt>Gem::Version</tt>
def self.gem_version
Gem::Version.new VERSION::STRING
end
diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb
index 4e6b02c246..1819d2403f 100644
--- a/activemodel/lib/active_model/naming.rb
+++ b/activemodel/lib/active_model/naming.rb
@@ -211,7 +211,7 @@ module ActiveModel
# BookModule::BookCover.model_name.i18n_key # => :"book_module/book_cover"
#
# Providing the functionality that ActiveModel::Naming provides in your object
- # is required to pass the Active Model Lint test. So either extending the
+ # is required to pass the \Active \Model Lint test. So either extending the
# provided method below, or rolling your own is required.
module Naming
def self.extended(base) #:nodoc:
diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb
index 8f2a069ba3..96e88f1b6c 100644
--- a/activemodel/lib/active_model/secure_password.rb
+++ b/activemodel/lib/active_model/secure_password.rb
@@ -99,7 +99,7 @@ module ActiveModel
# user.authenticate('notright') # => false
# user.authenticate('mUc3m00RsqyRe') # => user
def authenticate(unencrypted_password)
- BCrypt::Password.new(password_digest) == unencrypted_password && self
+ BCrypt::Password.new(password_digest).is_password?(unencrypted_password) && self
end
attr_reader :password
diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb
index 3ad3bf30ad..e33c766627 100644
--- a/activemodel/lib/active_model/serializers/xml.rb
+++ b/activemodel/lib/active_model/serializers/xml.rb
@@ -6,7 +6,7 @@ require 'active_support/core_ext/time/acts_like'
module ActiveModel
module Serializers
- # == Active Model XML Serializer
+ # == \Active \Model XML Serializer
module Xml
extend ActiveSupport::Concern
include ActiveModel::Serialization
diff --git a/activemodel/lib/active_model/validations/absence.rb b/activemodel/lib/active_model/validations/absence.rb
index 9b5416fb1d..75bf655578 100644
--- a/activemodel/lib/active_model/validations/absence.rb
+++ b/activemodel/lib/active_model/validations/absence.rb
@@ -1,6 +1,6 @@
module ActiveModel
module Validations
- # == Active Model Absence Validator
+ # == \Active \Model Absence Validator
class AbsenceValidator < EachValidator #:nodoc:
def validate_each(record, attr_name, value)
record.errors.add(attr_name, :present, options) if value.present?
diff --git a/activemodel/lib/active_model/validations/callbacks.rb b/activemodel/lib/active_model/validations/callbacks.rb
index 25ccabd66b..4b58ef66e3 100644
--- a/activemodel/lib/active_model/validations/callbacks.rb
+++ b/activemodel/lib/active_model/validations/callbacks.rb
@@ -15,15 +15,14 @@ module ActiveModel
# after_validation :do_stuff_after_validation
# end
#
- # Like other <tt>before_*</tt> callbacks if +before_validation+ returns
- # +false+ then <tt>valid?</tt> will not be called.
+ # Like other <tt>before_*</tt> callbacks if +before_validation+ throws
+ # +:abort+ then <tt>valid?</tt> will not be called.
module Callbacks
extend ActiveSupport::Concern
included do
include ActiveSupport::Callbacks
define_callbacks :validation,
- terminator: ->(_,result) { result == false },
skip_after_callbacks_if_terminated: true,
scope: [:kind, :name]
end
diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb
index 0116de68ab..ac32750946 100644
--- a/activemodel/lib/active_model/validator.rb
+++ b/activemodel/lib/active_model/validator.rb
@@ -127,7 +127,7 @@ module ActiveModel
# in the options hash invoking the <tt>validate_each</tt> method passing in the
# record, attribute and value.
#
- # All Active Model validations are built on top of this validator.
+ # All \Active \Model validations are built on top of this validator.
class EachValidator < Validator #:nodoc:
attr_reader :attributes
diff --git a/activemodel/lib/active_model/version.rb b/activemodel/lib/active_model/version.rb
index b1f9082ea7..6da3b4117b 100644
--- a/activemodel/lib/active_model/version.rb
+++ b/activemodel/lib/active_model/version.rb
@@ -1,7 +1,7 @@
require_relative 'gem_version'
module ActiveModel
- # Returns the version of the currently loaded ActiveModel as a <tt>Gem::Version</tt>
+ # Returns the version of the currently loaded \Active \Model as a <tt>Gem::Version</tt>
def self.version
gem_version
end
diff --git a/activemodel/test/cases/callbacks_test.rb b/activemodel/test/cases/callbacks_test.rb
index 2ac681b8d8..85455c112c 100644
--- a/activemodel/test/cases/callbacks_test.rb
+++ b/activemodel/test/cases/callbacks_test.rb
@@ -33,11 +33,13 @@ class CallbacksTest < ActiveModel::TestCase
def initialize(options = {})
@callbacks = []
@valid = options[:valid]
- @before_create_returns = options[:before_create_returns]
+ @before_create_returns = options.fetch(:before_create_returns, true)
+ @before_create_throws = options[:before_create_throws]
end
def before_create
@callbacks << :before_create
+ throw(@before_create_throws) if @before_create_throws
@before_create_returns
end
@@ -62,10 +64,18 @@ class CallbacksTest < ActiveModel::TestCase
assert_equal model.callbacks.last, :final_callback
end
- test "the callback chain is halted when a before callback returns false" do
+ test "the callback chain is halted when a before callback returns false (deprecated)" do
model = ModelCallbacks.new(before_create_returns: false)
+ assert_deprecated do
+ model.create
+ assert_equal model.callbacks.last, :before_create
+ end
+ end
+
+ test "the callback chain is halted when a callback throws :abort" do
+ model = ModelCallbacks.new(before_create_throws: :abort)
model.create
- assert_equal model.callbacks.last, :before_create
+ assert_equal model.callbacks, [:before_create]
end
test "after callbacks are not executed if the block returns false" do
diff --git a/activemodel/test/cases/dirty_test.rb b/activemodel/test/cases/dirty_test.rb
index db2cd885e2..8ffd62fd86 100644
--- a/activemodel/test/cases/dirty_test.rb
+++ b/activemodel/test/cases/dirty_test.rb
@@ -181,23 +181,6 @@ class DirtyTest < ActiveModel::TestCase
assert_equal ActiveSupport::HashWithIndifferentAccess.new, @model.changed_attributes
end
- test "reset_changes is deprecated" do
- @model.name = 'Dmitry'
- @model.name_changed?
- @model.save
- @model.name = 'Bob'
-
- assert_equal [nil, 'Dmitry'], @model.previous_changes['name']
- assert_equal 'Dmitry', @model.changed_attributes['name']
-
- assert_deprecated do
- @model.deprecated_reload
- end
-
- assert_equal ActiveSupport::HashWithIndifferentAccess.new, @model.previous_changes
- assert_equal ActiveSupport::HashWithIndifferentAccess.new, @model.changed_attributes
- end
-
test "restore_attributes should restore all previous data" do
@model.name = 'Dmitry'
@model.color = 'Red'
diff --git a/activemodel/test/cases/validations/callbacks_test.rb b/activemodel/test/cases/validations/callbacks_test.rb
index 5d6d48b824..4b0dd58efb 100644
--- a/activemodel/test/cases/validations/callbacks_test.rb
+++ b/activemodel/test/cases/validations/callbacks_test.rb
@@ -30,11 +30,16 @@ class DogWithTwoValidators < Dog
before_validation { self.history << 'before_validation_marker2' }
end
-class DogBeforeValidatorReturningFalse < Dog
+class DogDeprecatedBeforeValidatorReturningFalse < Dog
before_validation { false }
before_validation { self.history << 'before_validation_marker2' }
end
+class DogBeforeValidatorThrowingAbort < Dog
+ before_validation { throw :abort }
+ before_validation { self.history << 'before_validation_marker2' }
+end
+
class DogAfterValidatorReturningFalse < Dog
after_validation { false }
after_validation { self.history << 'after_validation_marker' }
@@ -86,13 +91,22 @@ class CallbacksWithMethodNamesShouldBeCalled < ActiveModel::TestCase
assert_equal ['before_validation_marker1', 'before_validation_marker2'], d.history
end
- def test_further_callbacks_should_not_be_called_if_before_validation_returns_false
- d = DogBeforeValidatorReturningFalse.new
+ def test_further_callbacks_should_not_be_called_if_before_validation_throws_abort
+ d = DogBeforeValidatorThrowingAbort.new
output = d.valid?
assert_equal [], d.history
assert_equal false, output
end
+ def test_deprecated_further_callbacks_should_not_be_called_if_before_validation_returns_false
+ d = DogDeprecatedBeforeValidatorReturningFalse.new
+ assert_deprecated do
+ output = d.valid?
+ assert_equal [], d.history
+ assert_equal false, output
+ end
+ end
+
def test_further_callbacks_should_be_called_if_after_validation_returns_false
d = DogAfterValidatorReturningFalse.new
d.valid?
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index cef66f3c0d..2b932683ea 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -171,9 +171,8 @@ class ValidationsTest < ActiveModel::TestCase
# A common mistake -- we meant to call 'validates'
Topic.validate :title, presence: true
end
- message = 'Unknown key: :presence. Valid keys are: :on, :if, :unless. Perhaps you meant to call `validates` instead of `validate`?'
- assert_includes error.message, "Unknown key: :presence"
- assert_includes error.message, "Perhaps you meant to call `validates` instead of `validate`?"
+ message = 'Unknown key: :presence. Valid keys are: :on, :if, :unless, :prepend. Perhaps you meant to call `validates` instead of `validate`?'
+ assert_equal message, error.message
end
def test_callback_options_to_validate