mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
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.
This commit is contained in:
parent
b12abe6733
commit
f072db8e4f
3 changed files with 43 additions and 2 deletions
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue