attributes_history 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 047e72c287edac9652bb432b71b3fe4b2e0e7822
|
4
|
+
data.tar.gz: fe7bcfe8813faff091440a3f591467c6d6c79dc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 07329646bcc03cfc94c4687339bf3f6296f3ddf85c8ec3c4d11114b72f15eb6c0dc0cd10492e35288c7c3a105b9ed958ec7f7fec9f32faee923376ae19f4133d
|
7
|
+
data.tar.gz: e09f2bf36bd530e5894c51f3c4cc575e6fe11e346acc395d00eea6afd08b277ec8af2285e5f77b7f75f233a45145e00348af80adcb4dc965857fb945425471b2
|
data/README.md
CHANGED
@@ -96,6 +96,24 @@ This is similar to how [paper_trail](https://github.com/airblade/paper_trail)
|
|
96
96
|
works in that the versions represent past data, and only the current regular
|
97
97
|
model record (contact in this case) has the current state.
|
98
98
|
|
99
|
+
## Multiple `has_attributes_history` calls per class
|
100
|
+
|
101
|
+
If you want to have some attributes (or groups of attributes) stored in
|
102
|
+
different tables grouped by semantic meaning or because their size or rate of
|
103
|
+
change is different, you can specify multiple `has_attributes_history` calls per
|
104
|
+
class. The lists of attributes for the different calls can't have any
|
105
|
+
overlapping attributes though or that will confuse the lookup logic.
|
106
|
+
|
107
|
+
Here's an example of tracking `notes` in a separate log from `status` and
|
108
|
+
`pledge`:
|
109
|
+
|
110
|
+
```
|
111
|
+
class Contact < ActiveRecord::Base
|
112
|
+
has_attributes_history for: [:status, :pledge], with_model: PartnerStatusLog
|
113
|
+
has_attributes_history for: [:notes], with_model: ContactNotesLog
|
114
|
+
end
|
115
|
+
```
|
116
|
+
|
99
117
|
## Enabling and disabling
|
100
118
|
|
101
119
|
By default the history logging is enabled once you set it up, but you can
|
@@ -6,22 +6,51 @@ module AttributesHistory
|
|
6
6
|
module HasAttributesHistory
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
+
included do
|
10
|
+
class_attribute :history_models, :history_associations
|
11
|
+
self.history_models ||= {}
|
12
|
+
self.history_associations ||= {}
|
13
|
+
end
|
14
|
+
|
9
15
|
module ClassMethods
|
10
16
|
# The options should include the keys :attributes and :version_class
|
11
17
|
def has_attributes_history(options)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
self.history_association = history_model.name.underscore.pluralize.to_sym
|
18
|
+
history_model = options[:with_model]
|
19
|
+
history_attributes = options[:for].map(&:to_s)
|
20
|
+
history_association = history_model.name.underscore.pluralize.to_sym
|
16
21
|
|
17
22
|
has_many history_association
|
18
|
-
|
19
|
-
|
23
|
+
|
24
|
+
store_history_options(history_model, history_attributes, history_association)
|
25
|
+
setup_history_callback(history_attributes, history_model)
|
26
|
+
define_attribute_on_date_methods(history_attributes)
|
27
|
+
end
|
28
|
+
|
29
|
+
def history_model(attribute)
|
30
|
+
self.history_models[attribute]
|
31
|
+
end
|
32
|
+
|
33
|
+
def history_association(attribute)
|
34
|
+
self.history_associations[attribute]
|
20
35
|
end
|
21
36
|
|
22
37
|
private
|
23
38
|
|
24
|
-
def
|
39
|
+
def store_history_options(history_model, history_attributes, history_association)
|
40
|
+
history_attributes.each do |attribute|
|
41
|
+
self.history_associations[attribute] = history_association
|
42
|
+
self.history_models[attribute] = history_model
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def setup_history_callback(history_attributes, history_model)
|
47
|
+
after_update do
|
48
|
+
HistorySaver.new(self, history_attributes, history_model)
|
49
|
+
.save_if_needed
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def define_attribute_on_date_methods(history_attributes)
|
25
54
|
define_method :attribute_on_date do |attribute, date|
|
26
55
|
@history_retriever ||= HistoryRetriever.new(self)
|
27
56
|
@history_retriever.attribute_on_date(attribute, date)
|
@@ -6,14 +6,18 @@ module AttributesHistory
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def attribute_on_date(attribute, date)
|
9
|
-
|
9
|
+
history_association = @object.class.history_association(attribute)
|
10
|
+
|
11
|
+
history_entry = @cached_history[[history_association, date]] ||=
|
12
|
+
find_entry_on(history_association, date)
|
13
|
+
|
10
14
|
history_entry.public_send(attribute)
|
11
15
|
end
|
12
16
|
|
13
17
|
private
|
14
18
|
|
15
|
-
def find_entry_on(date)
|
16
|
-
@object.public_send(
|
19
|
+
def find_entry_on(history_association, date)
|
20
|
+
@object.public_send(history_association)
|
17
21
|
.where('recorded_on > ?', date).order(:recorded_on).first || @object
|
18
22
|
end
|
19
23
|
end
|
@@ -1,7 +1,9 @@
|
|
1
1
|
module AttributesHistory
|
2
2
|
class HistorySaver
|
3
|
-
def initialize(changed_object)
|
3
|
+
def initialize(changed_object, history_attributes, history_model)
|
4
4
|
@object = changed_object
|
5
|
+
@history_attributes = history_attributes
|
6
|
+
@history_model = history_model
|
5
7
|
end
|
6
8
|
|
7
9
|
def save_if_needed
|
@@ -12,11 +14,14 @@ module AttributesHistory
|
|
12
14
|
private
|
13
15
|
|
14
16
|
def history_attributes_changed?
|
15
|
-
(@object.changed & @
|
17
|
+
(@object.changed & @history_attributes).present?
|
16
18
|
end
|
17
19
|
|
18
20
|
def save_history_entry
|
19
|
-
|
21
|
+
history_association =
|
22
|
+
@object.class.history_association(@history_attributes.first)
|
23
|
+
|
24
|
+
history_entry = @object.public_send(history_association)
|
20
25
|
.find_or_initialize_by(recorded_on: Date.current)
|
21
26
|
|
22
27
|
# If there is an existing history record for today, just leave it as is,
|
@@ -25,7 +30,7 @@ module AttributesHistory
|
|
25
30
|
end
|
26
31
|
|
27
32
|
def history_params
|
28
|
-
Hash[@
|
33
|
+
Hash[@history_attributes.map { |f| [f, history_value_for(f)] }]
|
29
34
|
end
|
30
35
|
|
31
36
|
def history_value_for(attribute)
|