-
Notifications
You must be signed in to change notification settings - Fork 186
/
Copy pathtrack_changes.rb
85 lines (76 loc) · 2.1 KB
/
track_changes.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
module ZendeskAPI
# Shamelessly stolen and modified from https://github.com/archan937/dirty_hashy
# @private
module TrackChanges
def self.included(base)
base.method_defined?(:regular_writer).tap do |defined|
base.send :include, InstanceMethods
unless defined
base.send :alias_method, :_store, :store
base.send :alias_method, :store, :regular_writer
base.send :alias_method, :[]=, :store
base.send :define_method, :update do |other|
other.each { |key, value| store key, value }
end
base.send :alias_method, :merge!, :update
end
end
end
# @private
module InstanceMethods
def clear_changes
each do |k, v|
if v.respond_to?(:clear_changes)
v.clear_changes
elsif v.is_a?(Array)
v.each do |val|
if val.respond_to?(:clear_changes)
val.clear_changes
end
end
end
end
changes.clear
end
def replace(other)
clear
merge! other
end
def clear
keys.each { |key| delete key }
end
def regular_writer(key, value)
if has_key?(key) && self[key] == value
value
else
changes[key] = value
defined?(_store) ? _store(key, value) : super(key, value)
end
end
def delete(key)
super.tap do |value|
changes[key] = nil
end
end
def changes
(@changes ||= self.class.superclass.new).tap do |changes|
each do |k, v|
if v.respond_to?(:changed?) && v.changed?
changes[k] = v.changes
elsif v.is_a?(Array) && v.any? { |val| val.respond_to?(:changed?) && val.changed? }
changes[k] = v
end
end
end
end
def changed?(key = nil)
if key.nil?
!changes.empty? || any? { |_, v| v.respond_to?(:changed?) && v.changed? }
else
changes.key?(key)
end
end
alias :dirty? :changed?
end
end
end