This repository has been archived by the owner on Oct 22, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathyarn_trackable.rb
82 lines (63 loc) · 2.14 KB
/
yarn_trackable.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
# encoding: utf-8
# A mixin that allows to simplify history tracking of model changes.
#
module Yarn::Trackable
module Head
extend ActiveSupport::Concern
included do
has_many history_association, -> { order 'revision' }, :inverse_of => :origin
end
module ClassMethods
def history_class
self.name.prepend('Old').constantize
end
def history_association
self.name.underscore.pluralize.prepend('old_').to_sym
end
end
def update_with_tracking(attrs = {}, save_method = :save)
self.class.transaction do
old_version = self.class.history_class.from_origin(self) if need_track?
self.author = attrs.delete(:author) if attrs[:author].present?
self.attributes = attrs if attrs.present?
yield self if block_given?
return self unless self.changed?
old_version.save! if old_version.present?
self.revision += 1
method(save_method).call.tap { |result| self.reload if result }
end
end
def need_track?
return false if new_record?
send(self.class.history_association).last.blank? ||
send(self.class.history_association).last.created_at < 12.hours.ago ||
send(self.class.history_association).last.author_id != author_id
end
end
module Tail
extend ActiveSupport::Concern
included do
association_class = origin_class.to_s
foreign_key = origin_class.to_s.foreign_key
inverse_of = self.name.underscore.pluralize.to_sym
belongs_to :origin,
class_name: association_class,
foreign_key: foreign_key,
inverse_of: inverse_of
end
module ClassMethods
def inverse_association
self.name.underscore.pluralize.to_sym
end
def origin_class
self.name.from(3).constantize
end
def from_origin(origin_entity)
attrs = origin_entity.attributes.reject {|k,_| %w(id updated_at).include? k }
attrs.merge!(created_at: origin_entity.updated_at)
history_entity = origin_entity.send(self.inverse_association).build(attrs, without_protection: true)
history_entity
end
end
end
end