Merge pull request #10816 from bogdan/less-dirty-dirty
Make AM::Dirty less dirty to plugin into AR or other library
This commit is contained in:
parent
782055674a
commit
9aa1a3d853
|
@ -1,3 +1,9 @@
|
||||||
|
* Added new API methods `reset_changes` and `changed_applied` to AM::Dirty
|
||||||
|
that control changes state. Previsously you needed to update internal
|
||||||
|
instance variables, but now API methods are available.
|
||||||
|
|
||||||
|
*Bogdan Gusiev*
|
||||||
|
|
||||||
* Fix has_secure_password. `password_confirmation` validations are triggered
|
* Fix has_secure_password. `password_confirmation` validations are triggered
|
||||||
even if no `password_confirmation` is set.
|
even if no `password_confirmation` is set.
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,7 @@ module ActiveModel
|
||||||
# track.
|
# track.
|
||||||
# * Call <tt>attr_name_will_change!</tt> before each change to the tracked
|
# * Call <tt>attr_name_will_change!</tt> before each change to the tracked
|
||||||
# attribute.
|
# attribute.
|
||||||
#
|
# * Call <tt>changes_applied</tt> after the changes are persisted.
|
||||||
# If you wish to also track previous changes on save or update, you need to
|
|
||||||
# add:
|
|
||||||
#
|
|
||||||
# @previously_changed = changes
|
|
||||||
#
|
|
||||||
# inside of your save or update method.
|
|
||||||
#
|
#
|
||||||
# A minimal implementation could be:
|
# A minimal implementation could be:
|
||||||
#
|
#
|
||||||
|
@ -39,8 +33,8 @@ module ActiveModel
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# def save
|
# def save
|
||||||
# @previously_changed = changes
|
# # do persistence work
|
||||||
# @changed_attributes.clear
|
# changes_applied
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
|
@ -129,7 +123,7 @@ module ActiveModel
|
||||||
# person.save
|
# person.save
|
||||||
# person.previous_changes # => {"name" => ["bob", "robert"]}
|
# person.previous_changes # => {"name" => ["bob", "robert"]}
|
||||||
def previous_changes
|
def previous_changes
|
||||||
@previously_changed
|
@previously_changed ||= {}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns a hash of the attributes with unsaved changes indicating their original
|
# Returns a hash of the attributes with unsaved changes indicating their original
|
||||||
|
@ -154,6 +148,18 @@ module ActiveModel
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# Removes current changes and makes them accessible through +previous_changes+.
|
||||||
|
def changes_applied
|
||||||
|
@previously_changed = changes
|
||||||
|
@changed_attributes = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Removes all dirty data: current changes and previous changes
|
||||||
|
def reset_changes
|
||||||
|
@previously_changed = {}
|
||||||
|
@changed_attributes = {}
|
||||||
|
end
|
||||||
|
|
||||||
# Handle <tt>*_change</tt> for +method_missing+.
|
# Handle <tt>*_change</tt> for +method_missing+.
|
||||||
def attribute_change(attr)
|
def attribute_change(attr)
|
||||||
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
|
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
|
||||||
|
|
|
@ -29,8 +29,7 @@ class DirtyTest < ActiveModel::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def save
|
def save
|
||||||
@previously_changed = changes
|
changes_applied
|
||||||
@changed_attributes.clear
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,7 @@ module ActiveRecord
|
||||||
# Attempts to +save+ the record and clears changed attributes if successful.
|
# Attempts to +save+ the record and clears changed attributes if successful.
|
||||||
def save(*)
|
def save(*)
|
||||||
if status = super
|
if status = super
|
||||||
@previously_changed = changes
|
changes_applied
|
||||||
@changed_attributes.clear
|
|
||||||
end
|
end
|
||||||
status
|
status
|
||||||
end
|
end
|
||||||
|
@ -28,16 +27,14 @@ module ActiveRecord
|
||||||
# Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
|
# Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
|
||||||
def save!(*)
|
def save!(*)
|
||||||
super.tap do
|
super.tap do
|
||||||
@previously_changed = changes
|
changes_applied
|
||||||
@changed_attributes.clear
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# <tt>reload</tt> the record and clears changed attributes.
|
# <tt>reload</tt> the record and clears changed attributes.
|
||||||
def reload(*)
|
def reload(*)
|
||||||
super.tap do
|
super.tap do
|
||||||
@previously_changed.clear
|
reset_changes
|
||||||
@changed_attributes.clear
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,11 +45,11 @@ module ActiveRecord
|
||||||
|
|
||||||
# The attribute already has an unsaved change.
|
# The attribute already has an unsaved change.
|
||||||
if attribute_changed?(attr)
|
if attribute_changed?(attr)
|
||||||
old = @changed_attributes[attr]
|
old = changed_attributes[attr]
|
||||||
@changed_attributes.delete(attr) unless _field_changed?(attr, old, value)
|
changed_attributes.delete(attr) unless _field_changed?(attr, old, value)
|
||||||
else
|
else
|
||||||
old = clone_attribute_value(:read_attribute, attr)
|
old = clone_attribute_value(:read_attribute, attr)
|
||||||
@changed_attributes[attr] = old if _field_changed?(attr, old, value)
|
changed_attributes[attr] = old if _field_changed?(attr, old, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Carry on.
|
# Carry on.
|
||||||
|
|
|
@ -413,8 +413,6 @@ module ActiveRecord
|
||||||
@aggregation_cache = {}
|
@aggregation_cache = {}
|
||||||
@association_cache = {}
|
@association_cache = {}
|
||||||
@attributes_cache = {}
|
@attributes_cache = {}
|
||||||
@previously_changed = {}
|
|
||||||
@changed_attributes = {}
|
|
||||||
@readonly = false
|
@readonly = false
|
||||||
@destroyed = false
|
@destroyed = false
|
||||||
@marked_for_destruction = false
|
@marked_for_destruction = false
|
||||||
|
@ -431,7 +429,7 @@ module ActiveRecord
|
||||||
# optimistic locking) won't get written unless they get marked as changed
|
# optimistic locking) won't get written unless they get marked as changed
|
||||||
self.class.columns.each do |c|
|
self.class.columns.each do |c|
|
||||||
attr, orig_value = c.name, c.default
|
attr, orig_value = c.name, c.default
|
||||||
@changed_attributes[attr] = orig_value if _field_changed?(attr, orig_value, @attributes[attr])
|
changed_attributes[attr] = orig_value if _field_changed?(attr, orig_value, @attributes[attr])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -434,7 +434,7 @@ module ActiveRecord
|
||||||
|
|
||||||
changes[self.class.locking_column] = increment_lock if locking_enabled?
|
changes[self.class.locking_column] = increment_lock if locking_enabled?
|
||||||
|
|
||||||
@changed_attributes.except!(*changes.keys)
|
changed_attributes.except!(*changes.keys)
|
||||||
primary_key = self.class.primary_key
|
primary_key = self.class.primary_key
|
||||||
self.class.unscoped.where(primary_key => self[primary_key]).update_all(changes) == 1
|
self.class.unscoped.where(primary_key => self[primary_key]).update_all(changes) == 1
|
||||||
end
|
end
|
||||||
|
|
|
@ -120,8 +120,8 @@ class Person
|
||||||
end
|
end
|
||||||
|
|
||||||
def save
|
def save
|
||||||
@previously_changed = changes
|
|
||||||
# do save work...
|
# do save work...
|
||||||
|
changes_applied
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
Loading…
Reference in New Issue