diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index 42f76cd656..a6efb61e4b 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,3 +1,11 @@
+* `*_previously_changed?` accepts `:from` and `:to` keyword arguments like `*_changed?`.
+
+ topic.update!(status: :archived)
+ topic.status_previously_changed?(from: "active", to: "archived")
+ # => true
+
+ *George Claghorn*
+
* Raise FrozenError when trying to write attributes that aren't backed by the database on an object that is frozen:
class Animal
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index 8297ed8fd7..1f67bc6555 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -83,6 +83,7 @@ module ActiveModel
#
# person.previous_changes # => {"name" => [nil, "Bill"]}
# person.name_previously_changed? # => true
+ # person.name_previously_changed?(from: nil, to: "Bill") # => true
# person.name_previous_change # => [nil, "Bill"]
# person.name_previously_was # => nil
# person.reload!
@@ -177,8 +178,8 @@ module ActiveModel
end
# Dispatch target for *_previously_changed? attribute methods.
- def attribute_previously_changed?(attr_name) # :nodoc:
- mutations_before_last_save.changed?(attr_name.to_s)
+ def attribute_previously_changed?(attr_name, **options) # :nodoc:
+ mutations_before_last_save.changed?(attr_name.to_s, **options)
end
# Dispatch target for *_previously_was attribute methods.
diff --git a/activemodel/test/cases/dirty_test.rb b/activemodel/test/cases/dirty_test.rb
index 96b3e0549d..cec5d9590e 100644
--- a/activemodel/test/cases/dirty_test.rb
+++ b/activemodel/test/cases/dirty_test.rb
@@ -149,6 +149,17 @@ class DirtyTest < ActiveModel::TestCase
assert_predicate @model, :name_previously_changed?
end
+ test "checking if an attribute was previously changed to a particular value" do
+ @model.name = "Ringo"
+ @model.save
+ assert @model.name_previously_changed?(from: nil, to: "Ringo")
+ assert_not @model.name_previously_changed?(from: "Pete", to: "Ringo")
+ assert @model.name_previously_changed?(to: "Ringo")
+ assert_not @model.name_previously_changed?(to: "Pete")
+ assert @model.name_previously_changed?(from: nil)
+ assert_not @model.name_previously_changed?(from: "Pete")
+ end
+
test "previous value is preserved when changed after save" do
assert_equal({}, @model.changed_attributes)
@model.name = "Paul"