55 lines
1.7 KiB
Ruby
55 lines
1.7 KiB
Ruby
# Add tracking of last changed attributes. Models including this module will be able to track attribute changes like:
|
|
# record.last_changed[:backup_created] #=> timestamp or nil
|
|
# record.last_changed.backup_created #=> timestamp or nil
|
|
module Dunlop::AttributeChangesTracking
|
|
extend ActiveSupport::Concern
|
|
|
|
included do
|
|
attr_accessor :attribute_change_time # add ability to synchronize changed_at time for collections
|
|
has_many :last_attribute_changes, as: :target, class_name: 'Dunlop::LastAttributeChange'
|
|
after_update :update_last_attribute_changed_at
|
|
end
|
|
|
|
def update_last_attribute_changed_at
|
|
changed_at = attribute_change_time || Time.now
|
|
(saved_changes.keys - self.class.ignore_attributes_for_last_change).each do |attr|
|
|
if existing = last_attribute_changes.find{|changed| changed.attribute_name == attr }
|
|
existing.update(changed_at: changed_at)
|
|
else
|
|
last_attribute_changes.create(changed_at: changed_at, attribute_name: attr)
|
|
end
|
|
end
|
|
end
|
|
|
|
def last_changed
|
|
@last_changed ||= LastChanged.new(self)
|
|
end
|
|
|
|
module ClassMethods
|
|
def with_last_attribute_changes
|
|
includes(:last_attribute_changes)
|
|
end
|
|
|
|
def ignore_attributes_for_last_change
|
|
%w[id sti_type created_at updated_at notes]
|
|
end
|
|
end
|
|
|
|
class LastChanged
|
|
attr_reader :target
|
|
def initialize(target)
|
|
@target = target
|
|
end
|
|
|
|
def method_missing(m, *args)
|
|
raise "#{target.class.name} has no attribute #{m}" unless target.has_attribute?(m)
|
|
self[m]
|
|
end
|
|
|
|
def [](val)
|
|
target.last_attribute_changes.find{|changed| changed.attribute_name == val.to_s }.try(:changed_at)
|
|
end
|
|
end
|
|
end
|
|
# owner_initialization.last_changed[attr]
|