snapshotable 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 +4 -4
- data/README.md +1 -5
- data/lib/services/snapshot_creator.rb +5 -5
- data/lib/snapshotable.rb +9 -58
- data/lib/snapshotable/model_config.rb +84 -0
- data/lib/snapshotable/snapshots.rb +57 -0
- data/lib/snapshotable/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 295739bcb71078e20aa642a39b554663b3eba3ed
|
4
|
+
data.tar.gz: 1aa27734ea1eceb4f18ef96e251cde73cc2b87a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
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
|
-
|
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 '
|
3
|
+
require 'snapshotable/snapshots'
|
4
4
|
|
5
5
|
module Snapshotable
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
63
|
-
|
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
|
data/lib/snapshotable/version.rb
CHANGED
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.
|
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
|