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: c5ab51f8fcbd9cad95f6e3724546f8f5d57fb848
4
- data.tar.gz: ecdc7309e290238fc6b21bf46c259b76f9dff6bc
3
+ metadata.gz: 047e72c287edac9652bb432b71b3fe4b2e0e7822
4
+ data.tar.gz: fe7bcfe8813faff091440a3f591467c6d6c79dc0
5
5
  SHA512:
6
- metadata.gz: 7c05774dccf3d142db49d91e8a949aa4cb4d80159c9839b36a31f62c5c7b2cc7cc82487d473e9c1ae432d651718fa21a5e38a136c12a1b886041a6ea58f2fd43
7
- data.tar.gz: d054f8a660744d412454a4c086bb881accbeb0cbc39db75115218ffa3a7b64abbb4efb50e5a67d603f8885547d0243fdce8a025450d4433f0fe15f863bc90967
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
@@ -1,3 +1,3 @@
1
1
  module AttributesHistory
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -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
- class_attribute :history_model, :history_attributes, :history_association
13
- self.history_model = options[:with_model]
14
- self.history_attributes = options[:for].map(&:to_s)
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
- after_update { HistorySaver.new(self).save_if_needed }
19
- define_verisons_by_date_lookups
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 define_verisons_by_date_lookups
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
- history_entry = @cached_history[date] ||= find_entry_on(date)
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(@object.history_association)
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 & @object.history_attributes).present?
17
+ (@object.changed & @history_attributes).present?
16
18
  end
17
19
 
18
20
  def save_history_entry
19
- history_entry = @object.public_send(@object.history_association)
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[@object.history_attributes.map { |f| [f, history_value_for(f)] }]
33
+ Hash[@history_attributes.map { |f| [f, history_value_for(f)] }]
29
34
  end
30
35
 
31
36
  def history_value_for(attribute)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attributes_history
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - draffensperger