aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
authorFernando Tapia Rico <fertapric@gmail.com>2015-04-21 18:56:43 +0200
committerFernando Tapia Rico <fertapric@gmail.com>2015-04-21 19:30:46 +0200
commitf072db8e4fb34cfd50840e8bf84fe90340cad5fe (patch)
tree9f0310fb93006c778cb00e7bcb71efc117ea74d2 /activemodel
parentb12abe673306f2b5298b7a296c74ddc9061d2fec (diff)
downloadrails-f072db8e4fb34cfd50840e8bf84fe90340cad5fe.tar.gz
rails-f072db8e4fb34cfd50840e8bf84fe90340cad5fe.tar.bz2
rails-f072db8e4fb34cfd50840e8bf84fe90340cad5fe.zip
Add `ActiveModel::Dirty#[attr_name]_previously_changed?` and
`ActiveModel::Dirty#[attr_name]_previous_change` to improve access to recorded changes after the model has been saved. It makes the dirty-attributes query methods consistent before and after saving.
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/CHANGELOG.md9
-rw-r--r--activemodel/lib/active_model/dirty.rb23
-rw-r--r--activemodel/test/cases/dirty_test.rb13
3 files changed, 43 insertions, 2 deletions
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index 32a2cb4517..e8ea660f15 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,3 +1,12 @@
+* Add `ActiveModel::Dirty#[attr_name]_previously_changed?` and
+ `ActiveModel::Dirty#[attr_name]_previous_change` to improve access
+ to recorded changes after the model has been saved.
+
+ It makes the dirty-attributes query methods consistent before and after
+ saving.
+
+ *Fernando Tapia Rico*
+
* Deprecate the `:tokenizer` option for `validates_length_of`, in favor of
plain Ruby.
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index c03e5fac79..c0fc507286 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -76,9 +76,11 @@ module ActiveModel
#
# Reset the changes:
#
- # person.previous_changes # => {"name" => ["Uncle Bob", "Bill"]}
+ # person.previous_changes # => {"name" => ["Uncle Bob", "Bill"]}
+ # person.name_previously_changed? # => true
+ # person.name_previous_change # => ["Uncle Bob", "Bill"]
# person.reload!
- # person.previous_changes # => {}
+ # person.previous_changes # => {}
#
# Rollback the changes:
#
@@ -115,6 +117,7 @@ module ActiveModel
included do
attribute_method_suffix '_changed?', '_change', '_will_change!', '_was'
+ attribute_method_suffix '_previously_changed?', '_previous_change'
attribute_method_affix prefix: 'restore_', suffix: '!'
end
@@ -179,6 +182,11 @@ module ActiveModel
attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
end
+ # Handles <tt>*_previously_changed?</tt> for +method_missing+.
+ def attribute_previously_changed?(attr, options = {}) #:nodoc:
+ previous_changes_include?(attr)
+ end
+
# Restore all previous data of the provided attributes.
def restore_attributes(attributes = changed)
attributes.each { |attr| restore_attribute! attr }
@@ -192,6 +200,12 @@ module ActiveModel
end
alias attribute_changed_by_setter? changes_include?
+ # Returns +true+ if attr_name were changed before the model was saved,
+ # +false+ otherwise.
+ def previous_changes_include?(attr_name)
+ @previously_changed.include?(attr_name)
+ end
+
# Removes current changes and makes them accessible through +previous_changes+.
def changes_applied # :doc:
@previously_changed = changes
@@ -209,6 +223,11 @@ module ActiveModel
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
end
+ # Handles <tt>*_previous_change</tt> for +method_missing+.
+ def attribute_previous_change(attr)
+ @previously_changed[attr] if attribute_previously_changed?(attr)
+ end
+
# Handles <tt>*_will_change!</tt> for +method_missing+.
def attribute_will_change!(attr)
return if attribute_changed?(attr)
diff --git a/activemodel/test/cases/dirty_test.rb b/activemodel/test/cases/dirty_test.rb
index 66ed8a350a..d17a12ad12 100644
--- a/activemodel/test/cases/dirty_test.rb
+++ b/activemodel/test/cases/dirty_test.rb
@@ -137,6 +137,19 @@ class DirtyTest < ActiveModel::TestCase
assert_equal [nil, "Jericho Cane"], @model.previous_changes['name']
end
+ test "setting new attributes should not affect previous changes" do
+ @model.name = "Jericho Cane"
+ @model.save
+ @model.name = "DudeFella ManGuy"
+ assert_equal [nil, "Jericho Cane"], @model.name_previous_change
+ end
+
+ test "saving should preserve model's previous changed status" do
+ @model.name = "Jericho Cane"
+ @model.save
+ assert @model.name_previously_changed?
+ end
+
test "previous value is preserved when changed after save" do
assert_equal({}, @model.changed_attributes)
@model.name = "Paul"