blob: 86bbd1d0028e8c110e0620d2371b0c0274d926fe (
plain)
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
86
87
88
89
90
91
|
module ChecksumSupport
extend ActiveSupport::Concern
SEPARATOR = '|'
VALUE_FOR_NIL_ATTRIBUTE = '-'
included do |into|
before_save :set_current_checksum_source, :update_checksum
Referential.register_model_with_checksum self
into.extend ClassMethods
end
module ClassMethods
def has_checksum_children klass, opts={}
parent_class = self
belongs_to = opts[:relation] || self.model_name.singular
has_many = opts[:relation] || self.model_name.plural
Rails.logger.debug "Define callback in #{klass} to update checksums #{self.model_name} (via #{has_many}/#{belongs_to})"
child_update_parent = Proc.new do
parents = []
parents << self.send(belongs_to) if klass.reflections[belongs_to].present?
parents += self.send(has_many) if klass.reflections[has_many].present?
Rails.logger.debug "Request from #{klass.name} checksum updates for #{parents.count} #{parent_class} parent(s)"
parents.compact.each &:update_checksum_without_callbacks!
end
klass.after_save &child_update_parent
klass.after_destroy &child_update_parent
end
end
def checksum_attributes
self.attributes.values
end
def checksum_replace_nil_or_empty_values values
# Replace empty array by nil & nil by VALUE_FOR_NIL_ATTRIBUTE
values
.map { |x| x.present? && x || VALUE_FOR_NIL_ATTRIBUTE }
.map do |item|
item =
if item.kind_of?(Array)
checksum_replace_nil_or_empty_values(item)
else
item
end
end
end
def current_checksum_source
source = checksum_replace_nil_or_empty_values(self.checksum_attributes)
source += self.custom_fields_checksum if self.respond_to?(:custom_fields_checksum)
source.map{ |item|
if item.kind_of?(Array)
item.map{ |x| x.kind_of?(Array) ? "(#{x.join(',')})" : x }.join(',')
else
item
end
}.join(SEPARATOR)
end
def set_current_checksum_source
self.checksum_source = self.current_checksum_source
end
def update_checksum
if self.checksum_source_changed?
self.checksum = Digest::SHA256.new.hexdigest(self.checksum_source)
Rails.logger.debug("Changed #{self.class.name}:#{id} checksum: #{self.checksum}")
end
end
def update_checksum!
_checksum_source = current_checksum_source
update checksum_source: _checksum_source, checksum: Digest::SHA256.new.hexdigest(_checksum_source)
Rails.logger.debug("Updated #{self.class.name}:#{id} checksum: #{self.checksum}")
end
def update_checksum_without_callbacks!
set_current_checksum_source
_checksum = Digest::SHA256.new.hexdigest(checksum_source)
Rails.logger.debug("Compute checksum for #{self.class.name}:#{id} checksum_source:'#{checksum_source}' checksum: #{_checksum}")
if _checksum != self.checksum
self.checksum = _checksum
self.class.where(id: self.id).update_all(checksum: _checksum, checksum_source: checksum_source) unless self.new_record?
Rails.logger.debug("Updated #{self.class.name}:#{id} checksum: #{self.checksum}")
end
end
end
|