1
0
Fork 0
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:
Fernando Tapia Rico 2015-04-21 18:56:43 +02:00
parent b12abe6733
commit f072db8e4f
3 changed files with 43 additions and 2 deletions

View file

@ -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 * Deprecate the `:tokenizer` option for `validates_length_of`, in favor of
plain Ruby. plain Ruby.

View file

@ -76,9 +76,11 @@ module ActiveModel
# #
# Reset the changes: # 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.reload!
# person.previous_changes # => {} # person.previous_changes # => {}
# #
# Rollback the changes: # Rollback the changes:
# #
@ -115,6 +117,7 @@ module ActiveModel
included do included do
attribute_method_suffix '_changed?', '_change', '_will_change!', '_was' attribute_method_suffix '_changed?', '_change', '_will_change!', '_was'
attribute_method_suffix '_previously_changed?', '_previous_change'
attribute_method_affix prefix: 'restore_', suffix: '!' attribute_method_affix prefix: 'restore_', suffix: '!'
end end
@ -179,6 +182,11 @@ module ActiveModel
attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr) attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
end 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. # Restore all previous data of the provided attributes.
def restore_attributes(attributes = changed) def restore_attributes(attributes = changed)
attributes.each { |attr| restore_attribute! attr } attributes.each { |attr| restore_attribute! attr }
@ -192,6 +200,12 @@ module ActiveModel
end end
alias attribute_changed_by_setter? changes_include? 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+. # Removes current changes and makes them accessible through +previous_changes+.
def changes_applied # :doc: def changes_applied # :doc:
@previously_changed = changes @previously_changed = changes
@ -209,6 +223,11 @@ module ActiveModel
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr) [changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
end 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+. # Handles <tt>*_will_change!</tt> for +method_missing+.
def attribute_will_change!(attr) def attribute_will_change!(attr)
return if attribute_changed?(attr) return if attribute_changed?(attr)

View file

@ -137,6 +137,19 @@ class DirtyTest < ActiveModel::TestCase
assert_equal [nil, "Jericho Cane"], @model.previous_changes['name'] assert_equal [nil, "Jericho Cane"], @model.previous_changes['name']
end 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 test "previous value is preserved when changed after save" do
assert_equal({}, @model.changed_attributes) assert_equal({}, @model.changed_attributes)
@model.name = "Paul" @model.name = "Paul"