module Logga::ActiveRecord

Constants

EXCLUDED_KEYS
EXCLUDED_SUFFIXES

Public Instance Methods

add_log_entries_for(*actions, to: :self, fields: {}, allowed_fields: [], exclude_fields: []) click to toggle source
# File lib/logga/active_record.rb, line 21
def add_log_entries_for(*actions, to: :self, fields: {}, allowed_fields: [], exclude_fields: [])
  after_create :log_model_creation if actions.include?(:create)
  after_destroy :log_model_deletion if actions.include?(:delete)
  after_update :log_model_changes if actions.include?(:update)
  define_method(:log_receiver) { to == :self ? self : send(to) }

  self.allowed_fields = Array(allowed_fields)
  self.excluded_fields = allowed_fields.blank? ? Array(exclude_fields) : []
  self.log_fields = fields
end
log_field_changes(changes) click to toggle source
# File lib/logga/active_record.rb, line 33
def log_field_changes(changes)
  return if changes.blank?

  body = field_changes_to_message(changes)
  create_log_entry(author_data.merge(body: body)) if body.present?
end
log_model_changes() click to toggle source
# File lib/logga/active_record.rb, line 56
def log_model_changes
  return if should_not_log?

  field_changes = previous_changes.reject { |k, _| reject_change?(k) }
  log_field_changes(field_changes)
end
log_model_creation() click to toggle source
# File lib/logga/active_record.rb, line 40
def log_model_creation
  return if should_not_log?

  body_generator = ->(record) { default_creation_log_body(record) }
  body = log_fields.fetch(:created_at, body_generator).call(self)
  create_log_entry(author_data.merge(body: body, created_at: creation_at))
end
log_model_deletion() click to toggle source
# File lib/logga/active_record.rb, line 48
def log_model_deletion
  return if should_not_log?

  body_generator = ->(record) { default_deletion_log_body(record) }
  body = log_fields.fetch(:deleted_at, body_generator).call(self)
  create_log_entry(author_data.merge(body: body))
end

Private Instance Methods

author_data() click to toggle source
# File lib/logga/active_record.rb, line 65
def author_data
  data = Hash(log_receiver.try(:author) || try(:author)).with_indifferent_access
  {
    author_id: data[:id],
    author_type: data[:type],
    author_name: data[:name]
  }
end
create_log_entry(entry) click to toggle source
# File lib/logga/active_record.rb, line 74
def create_log_entry(entry)
  log_receiver&.log_entries&.create(entry)
end
creation_at() click to toggle source
# File lib/logga/active_record.rb, line 78
def creation_at
  return Time.current unless log_receiver == self

  (log_receiver&.log_entries&.order(:created_at)&.first&.created_at || Time.current) - 0.1.seconds
end
default_change_log_body(record, field, _old_value, new_value) click to toggle source
# File lib/logga/active_record.rb, line 91
def default_change_log_body(record, field, _old_value, new_value)
  "#{titleized_model_class_name(record)} #{field.humanize(capitalize: false)} set to #{new_value}"
end
default_creation_log_body(record) click to toggle source
# File lib/logga/active_record.rb, line 84
def default_creation_log_body(record)
  [
    "#{titleized_model_class_name(record)} created",
    ("(#{record.state})" if record.try(:state))
  ].compact.join(" ")
end
default_deletion_log_body(record) click to toggle source
# File lib/logga/active_record.rb, line 95
def default_deletion_log_body(record)
  [
    "#{titleized_model_class_name(record)} removed",
    ("(#{record.name})" if record.try(:name))
  ].compact.join(" ")
end
field_changes_to_message(changes) click to toggle source
# File lib/logga/active_record.rb, line 102
def field_changes_to_message(changes)
  body_generator = lambda { |record, field, old_value, new_value|
    default_change_log_body(record, field, old_value, new_value)
  }
  changes.inject([]) do |result, (field, (old_value, new_value))|
    result << log_fields.fetch(field.to_sym, body_generator).call(self, field, old_value, new_value)
  end.compact.join("\n")
end
reject_change?(key) click to toggle source
# File lib/logga/active_record.rb, line 111
def reject_change?(key)
  sym_key = key.to_sym
  return allowed_fields.exclude?(sym_key) if allowed_fields.present?

  EXCLUDED_KEYS.include?(sym_key) ||
    (log_fields.exclude?(sym_key) &&
     (excluded_fields.include?(sym_key) ||
      EXCLUDED_SUFFIXES.any? { |suffix| key.to_s.end_with?(suffix.to_s) }))
end
should_not_log?() click to toggle source
# File lib/logga/active_record.rb, line 121
def should_not_log?
  !log_receiver.respond_to?(:log_entries)
end
titleized_model_class_name(record) click to toggle source
# File lib/logga/active_record.rb, line 125
def titleized_model_class_name(record)
  record.class.name.demodulize.titleize
end