snapshotable 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: acbed2ff58337c9ea062a66e6903534f8c438a38
4
- data.tar.gz: b673bec953e6067fe9baacc1447be0fa07109fcf
3
+ metadata.gz: 295739bcb71078e20aa642a39b554663b3eba3ed
4
+ data.tar.gz: 1aa27734ea1eceb4f18ef96e251cde73cc2b87a4
5
5
  SHA512:
6
- metadata.gz: 455c66dc663627512c89ec58a74e0c3be63b3a470e140a0ef3a32ca66f6fb952e2415eabae0a223c1378a70d232a0e06b963013e599a1f922fb84988ee8dda80
7
- data.tar.gz: 4f7b81e9cb19139b243a62e7cb0ec8a1d27539f980ec3752b37ed6b8cac7b97493a8598a8643b646f230f2cc7a36b14fbe81d4f2c37ef45db0178385c475c9fd
6
+ metadata.gz: e26506fecd06d327690dcda5a88a9a1ef557b3153e47bf4ca93ffd2b1fc95bb61dd3e657f2ef2c36325dcd9adda7c793975832ec8067a9a7ef1a49a45c1cfd4a
7
+ data.tar.gz: 5b6084efc5ff846800c97689f2cc8d3f28e05cf21cf86ea5a9bf53ce42572198763928bf7137cddef87c22b8cfd9e74b9bcfed4363397a9765833bdeb00ac612
data/README.md CHANGED
@@ -95,11 +95,7 @@ In this case, the model won't change, but you could modify it manually if you wi
95
95
 
96
96
  ### Setting the base model
97
97
 
98
- After creating the Snapshot model, add a `has_many` relation to the base model
99
- ```
100
- has_many user_snapshots, dependent: :destroy
101
- ```
102
- Then, set which attributes should be saved on the Snapshot using `snapshot` on the model
98
+ Set which attributes should be saved on the Snapshot using `snapshot` on the model
103
99
  ```
104
100
  snapshot :id, :name, :age, profile: [:description], photo: [:url], groups: [:name], friends: [:name, :age]
105
101
  ```
@@ -17,7 +17,7 @@ module Snapshotable
17
17
  def snapshot_attrs
18
18
  snapshot = {}
19
19
 
20
- add_custom_attributes(snapshot) if custom_snapshot_attributes.any?
20
+ add_custom_attributes(snapshot) if custom_snapshot_attributes&.any?
21
21
 
22
22
  snapshot[:object] = extract_attributes(record_snapshot_attrs, record) if record_snapshot_attrs.any?
23
23
 
@@ -27,7 +27,7 @@ module Snapshotable
27
27
  end
28
28
 
29
29
  def add_custom_attributes(snapshot)
30
- record.custom_snapshot_attributes.each do |key, attribute|
30
+ custom_snapshot_attributes.each do |key, attribute|
31
31
  snapshot[key] = record.send(attribute)
32
32
  end
33
33
  end
@@ -53,15 +53,15 @@ module Snapshotable
53
53
  end
54
54
 
55
55
  def record_snapshot_attrs
56
- @record_snapshot_attrs ||= record.attributes_to_save_on_snapshot.select { |attr| attr.is_a? Symbol }
56
+ @record_snapshot_attrs ||= record.class.attributes_to_save_on_snapshot.select { |attr| attr.is_a? Symbol }
57
57
  end
58
58
 
59
59
  def deep_snapshot_attrs
60
- @deep_snapshot_attrs ||= record.attributes_to_save_on_snapshot.select { |attr| attr.is_a? Hash }.first
60
+ @deep_snapshot_attrs ||= record.class.attributes_to_save_on_snapshot.select { |attr| attr.is_a? Hash }.first
61
61
  end
62
62
 
63
63
  def custom_snapshot_attributes
64
- @custom_snapshot_attributes ||= record.custom_snapshot_attributes
64
+ @custom_snapshot_attributes ||= record.class.custom_snapshot_attributes.first
65
65
  end
66
66
  end
67
67
  end
data/lib/snapshotable.rb CHANGED
@@ -1,70 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'services/snapshot_creator'
3
+ require 'snapshotable/snapshots'
4
4
 
5
5
  module Snapshotable
6
- # rubocop:disable Metrics/AbcSize
7
- # rubocop:disable Metrics/MethodLength
8
- # rubocop:disable Metrics/BlockLength
9
- def self.included(base)
10
- base.class_eval do
11
- extend ClassMethods
12
- class_attribute :attributes_to_save_on_snapshot, instance_writer: false
13
- class_attribute :attributes_to_ignore_on_diff, instance_writer: false
14
- class_attribute :custom_snapshot_attributes, instance_writer: false
15
-
16
- self.attributes_to_save_on_snapshot = []
17
- self.attributes_to_ignore_on_diff = %w[id created_at updated_at]
18
- self.custom_snapshot_attributes = {}
19
-
20
- unless instance_methods.include?(:take_snapshot!)
21
- def take_snapshot!
22
- snapshot = SnapshotCreator.new(self).call
23
- snapshot_model = Object.const_get("#{self.class.name}Snapshot")
24
-
25
- snapshot_model.create!(snapshot) if should_create_new_snapshot?(snapshot)
26
- end
27
- end
28
-
29
- unless instance_methods.include?(:last_snapshot)
30
- def last_snapshot
31
- send("#{self.class.name.downcase}_snapshots").last
32
- end
33
- end
34
-
35
- unless instance_methods.include?(:should_create_cache?)
36
- def should_create_new_snapshot?(snapshot)
37
- return true if last_snapshot.nil?
38
-
39
- snapshot_to_compare = last_snapshot
40
- .attributes
41
- .except(*attributes_to_ignore_on_diff)
42
- .with_indifferent_access
43
-
44
- HashDiff.diff(snapshot_to_compare, snapshot.with_indifferent_access).any?
45
- end
46
- end
47
- end
48
- end
49
- # rubocop:enable Metrics/AbcSize
50
- # rubocop:enable Metrics/MethodLength
51
- # rubocop:enable Metrics/BlockLength
52
-
53
- module ClassMethods
54
- def snapshot(*attributes)
55
- self.attributes_to_save_on_snapshot = attributes
56
- end
57
-
58
- def snapshot_ignore_diff(*attributes)
59
- self.attributes_to_ignore_on_diff = attributes.map(&:to_s)
6
+ class << self
7
+ # Switches Snapshotable on or off
8
+ def enabled=(value)
9
+ Snapshotable.config.enabled = value
60
10
  end
61
11
 
62
- def custom_snapshot(*attributes)
63
- self.custom_snapshot_attributes = attributes.first
12
+ # Returns if Snapshotable is turned on
13
+ def enabled?
14
+ Snapshotable.config.enabled.present?
64
15
  end
65
16
  end
66
17
  end
67
18
 
68
19
  ActiveSupport.on_load :active_record do
69
- include Snapshotable
20
+ include Snapshotable::Model
70
21
  end
@@ -0,0 +1,84 @@
1
+ module Snapshotable
2
+ class ModelConfig
3
+ DEFAULT_ATTRIBUTES = [].freeze
4
+ DEFAULT_IGNORE_ATTRIBUTES = %w[id created_at updated_at].freeze
5
+ DEFAULT_CUSTOM_ATTRIBUTES = {}.freeze
6
+
7
+ def initialize(model)
8
+ @model = model
9
+ end
10
+
11
+ def setup_snapshot
12
+ setup_snapshot_names
13
+ setup_variables
14
+ setup_association(@model)
15
+
16
+ @model.send :include, ::Snapshotable::Model::InstanceMethods
17
+ end
18
+
19
+ def setup_snapshot_attributes(attributes)
20
+ setup_snapshot unless snapshot_configured?
21
+ @model.attributes_to_save_on_snapshot = attributes || DEFAULT_ATTRIBUTES
22
+ end
23
+
24
+ def setup_snapshot_ignore(attributes)
25
+ setup_snapshot unless snapshot_configured?
26
+ @model.attributes_to_ignore_on_diff = attributes || DEFAULT_IGNORE_ATTRIBUTES
27
+ end
28
+
29
+ def setup_snapshot_custom(attributes)
30
+ setup_snapshot unless snapshot_configured?
31
+ @model.custom_snapshot_attributes = attributes || DEFAULT_CUSTOM_ATTRIBUTES
32
+ end
33
+
34
+ def snapshot_configured?
35
+ @model.respond_to?(:snapshot_configured) && @model.snapshot_configured
36
+ end
37
+
38
+ def setup_variables
39
+ @model.class_attribute :attributes_to_save_on_snapshot, instance_writer: false
40
+ @model.attributes_to_save_on_snapshot = DEFAULT_ATTRIBUTES
41
+ @model.send :attr_accessor, :attributes_to_save_on_snapshot
42
+
43
+ @model.class_attribute :attributes_to_ignore_on_diff, instance_writer: false
44
+ @model.attributes_to_ignore_on_diff = DEFAULT_IGNORE_ATTRIBUTES
45
+ @model.send :attr_accessor, :attributes_to_ignore_on_diff
46
+
47
+ @model.class_attribute :custom_snapshot_attributes, instance_writer: false
48
+ @model.custom_snapshot_attributes = DEFAULT_CUSTOM_ATTRIBUTES
49
+ @model.send :attr_accessor, :custom_snapshot_attributes
50
+
51
+ @model.class_attribute :snapshot_configured
52
+ @model.snapshot_configured = true
53
+ @model.send :attr_accessor, :snapshot_configured
54
+ end
55
+
56
+ def setup_snapshot_names
57
+ @model.class_attribute :snapshot_association_name
58
+ @model.snapshot_association_name = snapshot_association_name
59
+
60
+ @model.class_attribute :snapshot_class_name
61
+ @model.snapshot_class_name = snapshot_class_name
62
+ end
63
+
64
+ def setup_association(klass)
65
+ klass.has_many(
66
+ klass.snapshot_association_name,
67
+ class_name: klass.snapshot_class_name,
68
+ dependent: :destroy
69
+ )
70
+ end
71
+
72
+ def snapshot_class_name
73
+ "#{@model.name}Snapshot"
74
+ end
75
+
76
+ def snapshot_association_name
77
+ snapshot_class_name.pluralize.underscore.to_sym
78
+ end
79
+
80
+ def snapshot_foreign_key
81
+ "#{@model.name.downcase}_id"
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'services/snapshot_creator'
4
+ require 'snapshotable/model_config'
5
+
6
+ module Snapshotable
7
+ module Model
8
+ def self.included(base)
9
+ base.send :extend, ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+ def snapshot(*attributes)
14
+ snapshotable_config.setup_snapshot_attributes(attributes)
15
+ end
16
+
17
+ def snapshot_ignore_diff(*attributes)
18
+ snapshotable_config.setup_snapshot_ignore(attributes)
19
+ end
20
+
21
+ def custom_snapshot(*attributes)
22
+ snapshotable_config.setup_snapshot_custom(attributes)
23
+ end
24
+
25
+ def snapshotable_config
26
+ ::Snapshotable::ModelConfig.new(self)
27
+ end
28
+ end
29
+
30
+ module InstanceMethods
31
+ def take_snapshot!
32
+ snapshot = SnapshotCreator.new(self).call
33
+ snapshot_class.create!(snapshot) if should_create_new_snapshot?(snapshot)
34
+ end
35
+
36
+ def snapshots
37
+ send(snapshot_association_name)
38
+ end
39
+
40
+ def snapshot_class
41
+ Object.const_get(snapshot_class_name)
42
+ end
43
+
44
+ def should_create_new_snapshot?(snapshot)
45
+ last_snapshot = snapshots.last
46
+ return true if last_snapshot.nil?
47
+
48
+ snapshot_to_compare = last_snapshot
49
+ .attributes
50
+ .except(*self.class.attributes_to_ignore_on_diff)
51
+ .with_indifferent_access
52
+
53
+ HashDiff.diff(snapshot_to_compare, snapshot.with_indifferent_access).any?
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Snapshotable
4
- VERSION = '0.0.2'.freeze
4
+ VERSION = '0.0.3'.freeze
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snapshotable
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
  - João Batista Marinho
@@ -166,6 +166,8 @@ files:
166
166
  - lib/generators/snapshotable/templates/model.rb
167
167
  - lib/services/snapshot_creator.rb
168
168
  - lib/snapshotable.rb
169
+ - lib/snapshotable/model_config.rb
170
+ - lib/snapshotable/snapshots.rb
169
171
  - lib/snapshotable/version.rb
170
172
  - lib/tasks/cacheable_models.rake
171
173
  homepage: https://github.com/QultureRocks/snapshotable