Skip to content

Instantly share code, notes, and snippets.

@stympy
Created July 16, 2020 20:39
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stympy/642ac76c0716b7e4c5c6cffbecf199b7 to your computer and use it in GitHub Desktop.
Save stympy/642ac76c0716b7e4c5c6cffbecf199b7 to your computer and use it in GitHub Desktop.
Simple change tracking for Rails models. It also works for non-database-backed models with optional change tracking.
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
include ActivityLogger
end
module ActivityLogger
extend ActiveSupport::Concern
included do
[["create", "created"], ["update", "updated"], ["destroy", "destroyed"]].each do |meth, action|
if respond_to?("after_#{meth}")
send("after_#{meth}", -> { log_activity(action) })
end
end
end
protected
def activity_data
respond_to?(:saved_changes) && saved_changes.any? ? {changes: saved_changes.except("created_at", "updated_at")} : {}
end
def activity_attributes
attributes.slice("id", "name")
end
def log_activity(action, data: nil)
data ||= activity_attributes.merge(activity_data)
# This assumes Current.user is set in a controller, but it will work without it
ActiveSupport::Notifications.instrument("activity", {event: "#{action}-#{model_name.singular}", user_id: Current.user&.id, data: data})
end
end
ActiveSupport::Notifications.subscribe("activity") do |*args|
event = ActiveSupport::Notifications::Event.new(*args)
Rails.logger.info({ activity: event.payload.compact }.to_json)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment