Created
September 30, 2015 20:41
-
-
Save smook1980/6e95f1c903167bff3d59 to your computer and use it in GitHub Desktop.
A Mixin To Add Attribute Change Tracking to Models
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'active_support/concern' | |
module Model | |
ChangeEvent = Struct.new(:event, :condition) | |
class ChangeTracker | |
def initialize | |
@attributes = {} | |
end | |
def track(attribute, event:, condition:) | |
@attributes[attribute.to_s.freeze] = ChangeEvent.new(event, condition) | |
end | |
def process_changeset(client, changes) | |
@attributes.keys.each do |attribute| | |
old, new = changes[attribute] | |
process(client, @attributes[attribute], old, new) | |
end | |
end | |
private | |
def process(client, change_event, old_value, new_value) | |
if is_valid(change_event, old_value, new_value) | |
# TrackingEvents.create!(...) | |
puts "Trigger #{change_event.event} event for model attribute change from #{old_value} to #{new_value}" | |
else | |
puts "Did not trigger #{change_event.event} event for model attribute change from #{old_value} to #{new_value}, condition returned false." | |
end | |
end | |
def is_valid(change_event, old_value, new_value) | |
change_event.condition.call(old_value, new_value) | |
end | |
end | |
module ChangeTracking | |
extend ActiveSupport::Concern | |
class_methods do | |
def change_tracking_tracker | |
@change_tracking_tracker ||= ChangeTracker.new | |
end | |
def track(attribute, event:, condition:) | |
change_tracking_tracker.track(attribute, event: event, condition: condition) | |
end | |
end | |
included do | |
around_update :trigger_for_update | |
def trigger_for_update | |
raise 'Model must respond to "client" when implement ChangeTracking!'.freeze unless self.respond_to? :client | |
puts "*" * 50 | |
changeset = changes | |
puts "Triggering change event for attributes: #{changeset}" | |
# Run update SQL... | |
yield | |
# Trigger change events if need be... | |
self.class.change_tracking_tracker.process_changeset(client, changeset) | |
puts "*" * 50 | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An example of how this would be used: