Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make some methods in Dirty module public #627

Merged
merged 3 commits into from
Jan 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
112 changes: 56 additions & 56 deletions lib/dynamoid/dirty.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,18 @@ module Dirty
module ClassMethods
def update_fields(*)
super.tap do |model|
model.send(:clear_changes_information) if model
model.clear_changes_information if model
end
end

def upsert(*)
super.tap do |model|
model.send(:clear_changes_information) if model
model.clear_changes_information if model
end
end

def from_database(*)
super.tap do |m|
m.send(:clear_changes_information)
end
super.tap(&:clear_changes_information)
end
end

Expand Down Expand Up @@ -110,7 +108,7 @@ def changed
#
# @return [ActiveSupport::HashWithIndifferentAccess]
def changes
ActiveSupport::HashWithIndifferentAccess[changed.map { |attr| [attr, attribute_change(attr)] }]
ActiveSupport::HashWithIndifferentAccess[changed.map { |name| [name, attribute_change(name)] }]
end

# Returns a hash of attributes that were changed before the model was saved.
Expand All @@ -137,6 +135,25 @@ def changed_attributes
@changed_attributes ||= ActiveSupport::HashWithIndifferentAccess.new
end

# Clear all dirty data: current changes and previous changes.
def clear_changes_information
@previously_changed = ActiveSupport::HashWithIndifferentAccess.new
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
end

# Clears dirty data and moves +changes+ to +previous_changes+.
def changes_applied
@previously_changed = changes
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
end

# Remove changes information for the provided attributes.
#
# @param attributes [Array[String]] - a list of attributes to clear changes for
def clear_attribute_changes(names)
attributes_changed_by_setter.except!(*names)
end

# Handle <tt>*_changed?</tt> for +method_missing+.
#
# person.attribute_changed?(:name) # => true
Expand All @@ -145,14 +162,14 @@ def changed_attributes
# person.attribute_changed?(:name, from: 'Alice', to: 'Bod')
#
# @private
# @param attr [Symbol] attribute name
# @param name [Symbol] attribute name
# @param options [Hash] conditions on +from+ and +to+ value (optional)
# @option options [Symbol] :from previous attribute value
# @option options [Symbol] :to current attribute value
def attribute_changed?(attr, options = {})
result = changes_include?(attr)
result &&= options[:to] == __send__(attr) if options.key?(:to)
result &&= options[:from] == changed_attributes[attr] if options.key?(:from)
def attribute_changed?(name, options = {})
result = changes_include?(name)
result &&= options[:to] == read_attribute(name) if options.key?(:to)
result &&= options[:from] == changed_attributes[name] if options.key?(:from)
result
end

Expand All @@ -163,16 +180,16 @@ def attribute_changed?(attr, options = {})
# person.attribute_was(:name) # => "Alice"
#
# @private
# @param attr [Symbol] attribute name
def attribute_was(attr)
attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
# @param name [Symbol] attribute name
def attribute_was(name)
attribute_changed?(name) ? changed_attributes[name] : read_attribute(name)
end

# Restore all previous data of the provided attributes.
#
# @param attributes [Array[Symbol]] a list of attribute names
def restore_attributes(attributes = changed)
attributes.each { |attr| restore_attribute! attr }
def restore_attributes(names = changed)
names.each { |name| restore_attribute! name }
end

# Handles <tt>*_previously_changed?</tt> for +method_missing+.
Expand All @@ -183,10 +200,10 @@ def restore_attributes(attributes = changed)
# person.attribute_changed?(:name) # => true
#
# @private
# @param attr [Symbol] attribute name
# @param name [Symbol] attribute name
# @return [true|false]
def attribute_previously_changed?(attr)
previous_changes_include?(attr)
def attribute_previously_changed?(name)
previous_changes_include?(name)
end

# Handles <tt>*_previous_change</tt> for +method_missing+.
Expand All @@ -197,75 +214,58 @@ def attribute_previously_changed?(attr)
# person.attribute_previously_changed(:name) # => ["Alice", "Bob"]
#
# @private
# @param attr [Symbol]
# @param name [Symbol]
# @return [Array]
def attribute_previous_change(attr)
previous_changes[attr] if attribute_previously_changed?(attr)
def attribute_previous_change(name)
previous_changes[name] if attribute_previously_changed?(name)
end

private

def changes_include?(attr_name)
attributes_changed_by_setter.include?(attr_name)
def changes_include?(name)
attributes_changed_by_setter.include?(name)
end
alias attribute_changed_by_setter? changes_include?

# Removes current changes and makes them accessible through +previous_changes+.
def changes_applied # :doc:
@previously_changed = changes
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
end

# Clear all dirty data: current changes and previous changes.
def clear_changes_information # :doc:
@previously_changed = ActiveSupport::HashWithIndifferentAccess.new
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
end

# Handle <tt>*_change</tt> for +method_missing+.
def attribute_change(attr)
[changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
def attribute_change(name)
[changed_attributes[name], read_attribute(name)] if attribute_changed?(name)
end

# Handle <tt>*_will_change!</tt> for +method_missing+.
def attribute_will_change!(attr)
return if attribute_changed?(attr)
def attribute_will_change!(name)
return if attribute_changed?(name)

begin
value = __send__(attr)
value = read_attribute(name)
value = value.duplicable? ? value.clone : value
rescue TypeError, NoMethodError
end

set_attribute_was(attr, value)
set_attribute_was(name, value)
end

# Handle <tt>restore_*!</tt> for +method_missing+.
def restore_attribute!(attr)
if attribute_changed?(attr)
__send__("#{attr}=", changed_attributes[attr])
clear_attribute_changes([attr])
def restore_attribute!(name)
if attribute_changed?(name)
write_attribute(name, changed_attributes[name])
clear_attribute_changes([name])
end
end

# Returns +true+ if attr_name were changed before the model was saved,
# Returns +true+ if name were changed before the model was saved,
# +false+ otherwise.
def previous_changes_include?(attr_name)
previous_changes.include?(attr_name)
def previous_changes_include?(name)
previous_changes.include?(name)
end

# This is necessary because `changed_attributes` might be overridden in
# other implemntations (e.g. in `ActiveRecord`)
alias attributes_changed_by_setter changed_attributes

# Force an attribute to have a particular "before" value
def set_attribute_was(attr, old_value)
attributes_changed_by_setter[attr] = old_value
end

# Remove changes information for the provided attributes.
def clear_attribute_changes(attributes)
attributes_changed_by_setter.except!(*attributes)
def set_attribute_was(name, old_value)
attributes_changed_by_setter[name] = old_value
end
end
end