141 lines
3.6 KiB
Ruby
141 lines
3.6 KiB
Ruby
|
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
||
|
module Historisable
|
||
|
extend ActiveSupport::Concern
|
||
|
|
||
|
included do
|
||
|
attr_accessor :history_changes_last_done
|
||
|
|
||
|
after_create :history_create
|
||
|
after_update :history_update
|
||
|
after_destroy :history_destroy
|
||
|
end
|
||
|
|
||
|
=begin
|
||
|
|
||
|
log object create history, if configured - will be executed automatically
|
||
|
|
||
|
model = Model.find(123)
|
||
|
model.history_create
|
||
|
|
||
|
=end
|
||
|
|
||
|
def history_create
|
||
|
history_log('created', created_by_id)
|
||
|
end
|
||
|
|
||
|
=begin
|
||
|
|
||
|
log object update history with all updated attributes, if configured - will be executed automatically
|
||
|
|
||
|
model = Model.find(123)
|
||
|
model.history_update
|
||
|
|
||
|
=end
|
||
|
|
||
|
def history_update
|
||
|
return if !changed?
|
||
|
|
||
|
# return if it's no update
|
||
|
return if new_record?
|
||
|
|
||
|
# new record also triggers update, so ignore new records
|
||
|
changes = self.changes
|
||
|
if history_changes_last_done
|
||
|
history_changes_last_done.each { |key, value|
|
||
|
if changes.key?(key) && changes[key] == value
|
||
|
changes.delete(key)
|
||
|
end
|
||
|
}
|
||
|
end
|
||
|
self.history_changes_last_done = changes
|
||
|
#logger.info 'updated ' + self.changes.inspect
|
||
|
|
||
|
return if changes['id'] && !changes['id'][0]
|
||
|
|
||
|
ignored_attributes = self.class.instance_variable_get(:@history_attributes_ignored) || []
|
||
|
ignored_attributes += %i(created_at updated_at created_by_id updated_by_id)
|
||
|
|
||
|
changes.each { |key, value|
|
||
|
|
||
|
next if ignored_attributes.include?(key.to_sym)
|
||
|
|
||
|
# get attribute name
|
||
|
attribute_name = key.to_s
|
||
|
if attribute_name[-3, 3] == '_id'
|
||
|
attribute_name = attribute_name[ 0, attribute_name.length - 3 ]
|
||
|
end
|
||
|
|
||
|
value_id = []
|
||
|
value_str = [ value[0], value[1] ]
|
||
|
if key.to_s[-3, 3] == '_id'
|
||
|
value_id[0] = value[0]
|
||
|
value_id[1] = value[1]
|
||
|
|
||
|
if respond_to?(attribute_name) && send(attribute_name)
|
||
|
relation_class = send(attribute_name).class
|
||
|
if relation_class && value_id[0]
|
||
|
relation_model = relation_class.lookup(id: value_id[0])
|
||
|
if relation_model
|
||
|
if relation_model['name']
|
||
|
value_str[0] = relation_model['name']
|
||
|
elsif relation_model.respond_to?('fullname')
|
||
|
value_str[0] = relation_model.send('fullname')
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
if relation_class && value_id[1]
|
||
|
relation_model = relation_class.lookup(id: value_id[1])
|
||
|
if relation_model
|
||
|
if relation_model['name']
|
||
|
value_str[1] = relation_model['name']
|
||
|
elsif relation_model.respond_to?('fullname')
|
||
|
value_str[1] = relation_model.send('fullname')
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
data = {
|
||
|
history_attribute: attribute_name,
|
||
|
value_from: value_str[0].to_s,
|
||
|
value_to: value_str[1].to_s,
|
||
|
id_from: value_id[0],
|
||
|
id_to: value_id[1],
|
||
|
}
|
||
|
#logger.info "HIST NEW #{self.class.to_s}.find(#{self.id}) #{data.inspect}"
|
||
|
history_log('updated', updated_by_id, data)
|
||
|
}
|
||
|
end
|
||
|
|
||
|
=begin
|
||
|
|
||
|
delete object history, will be executed automatically
|
||
|
|
||
|
model = Model.find(123)
|
||
|
model.history_destroy
|
||
|
|
||
|
=end
|
||
|
|
||
|
def history_destroy
|
||
|
History.remove(self.class.to_s, id)
|
||
|
end
|
||
|
|
||
|
# methods defined here are going to extend the class, not the instance of it
|
||
|
class_methods do
|
||
|
=begin
|
||
|
|
||
|
serve methode to ignore model attributes in historization
|
||
|
|
||
|
class Model < ApplicationModel
|
||
|
include Historisable
|
||
|
history_attributes_ignored :create_article_type_id, :preferences
|
||
|
end
|
||
|
|
||
|
=end
|
||
|
|
||
|
def history_attributes_ignored(*attributes)
|
||
|
@history_attributes_ignored = attributes
|
||
|
end
|
||
|
end
|
||
|
end
|