recorder 0.1.3 → 0.1.4
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/lib/generators/recorder/install_generator.rb +19 -3
- data/lib/generators/recorder/templates/add_index_by_user_id_to_recorder_revisions.rb +6 -0
- data/lib/generators/recorder/templates/add_number_column_to_recorder_revisions.rb +41 -0
- data/lib/generators/recorder/templates/create_recorder_revisions.rb +1 -1
- data/lib/recorder/changeset.rb +0 -4
- data/lib/recorder/observer.rb +1 -1
- data/lib/recorder/revision.rb +28 -0
- data/lib/recorder/tape.rb +39 -18
- data/lib/recorder/version.rb +1 -1
- data/lib/recorder.rb +5 -8
- data/recorder.gemspec +1 -0
- metadata +19 -3
- data/lib/recorder/draper/decorator_concern.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4550b7a532edd1f5ce2c56036803a96ca4f8242
|
4
|
+
data.tar.gz: 4051cdb776fe3d7c25ad879547cd56dae3ae35ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73714c8436f37e393705489ecfe4ea23d805cec43bf158e3b920945e246bd48d631fb48c7c07c4e114ce9a891b7ac857293faa099a8a63f08a2cb15c1e29838f
|
7
|
+
data.tar.gz: c3030783723e4d3e59ae67fabc6e2bd3f18c718f2339893375b750c54ad2d7cfdbcd6bfded0c7d08b115edc2adbe8c1a122b4b4091b64b98fc60ef3dc9e8a190
|
@@ -12,14 +12,30 @@ module Recorder
|
|
12
12
|
:with_partitions,
|
13
13
|
type: :boolean,
|
14
14
|
default: false,
|
15
|
-
desc: "Create partitions
|
15
|
+
desc: "Create partitions to `recorder_revisions` table"
|
16
16
|
)
|
17
17
|
|
18
|
-
|
18
|
+
class_option(
|
19
|
+
:with_number_column,
|
20
|
+
type: :boolean,
|
21
|
+
default: false,
|
22
|
+
desc: "Add `number` column to `recorder_revisions` table"
|
23
|
+
)
|
24
|
+
|
25
|
+
class_option(
|
26
|
+
:with_index_by_user_id,
|
27
|
+
type: :boolean,
|
28
|
+
default: false,
|
29
|
+
desc: "Add index by `user_id` column to `recorder_revisions` table"
|
30
|
+
)
|
31
|
+
|
32
|
+
desc "Generates (but does not run) a migration to add a `recorder_revisions` table."
|
19
33
|
|
20
34
|
def create_migration_file
|
21
35
|
self.add_or_skip_recorder_migration('create_recorder_revisions')
|
22
|
-
self.add_or_skip_recorder_migration('
|
36
|
+
self.add_or_skip_recorder_migration('add_number_column_to_recorder_revisions') if options.with_number_column?
|
37
|
+
self.add_or_skip_recorder_migration('add_index_by_user_id_to_recorder_revisions') if options.with_index_by_user_id?
|
38
|
+
self.add_or_skip_recorder_migration('add_partitions_to_recorder_revisions') if options.with_partitions?
|
23
39
|
end
|
24
40
|
|
25
41
|
def self.next_migration_number(dirname)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# This migration adds number column to the `revisions` table.
|
2
|
+
class AddNumberColumnToRecorderRevisions < ActiveRecord::Migration
|
3
|
+
def up
|
4
|
+
add_column :recorder_revisions, :number, :integer, :null => false, :default => 0
|
5
|
+
|
6
|
+
execute <<-SQL
|
7
|
+
CREATE OR REPLACE FUNCTION get_recorder_revisions_number()
|
8
|
+
RETURNS trigger AS
|
9
|
+
$BODY$
|
10
|
+
BEGIN
|
11
|
+
SELECT COALESCE(MAX(recorder_revisions.number), 0) + 1
|
12
|
+
INTO NEW.number
|
13
|
+
FROM
|
14
|
+
recorder_revisions
|
15
|
+
WHERE
|
16
|
+
recorder_revisions.item_type = NEW.item_type
|
17
|
+
AND recorder_revisions.item_id = NEW.item_id;
|
18
|
+
|
19
|
+
RETURN NEW;
|
20
|
+
END;
|
21
|
+
$BODY$ LANGUAGE plpgsql;
|
22
|
+
SQL
|
23
|
+
|
24
|
+
execute <<-SQL
|
25
|
+
CREATE TRIGGER update_recorder_revisions_number BEFORE INSERT ON recorder_revisions FOR EACH ROW
|
26
|
+
EXECUTE PROCEDURE get_recorder_revisions_number();
|
27
|
+
SQL
|
28
|
+
end
|
29
|
+
|
30
|
+
def down
|
31
|
+
execute <<-SQL
|
32
|
+
DROP TRIGGER update_recorder_revisions_number;
|
33
|
+
SQL
|
34
|
+
|
35
|
+
execute <<-SQL
|
36
|
+
DROP FUNCTION IF EXISTS get_recorder_revisions_number;
|
37
|
+
SQL
|
38
|
+
|
39
|
+
remove_column :recorder_revisions, :number
|
40
|
+
end
|
41
|
+
end
|
data/lib/recorder/changeset.rb
CHANGED
@@ -16,12 +16,9 @@ module Recorder
|
|
16
16
|
else
|
17
17
|
self.item.class.human_attribute_name(attribute.to_s)
|
18
18
|
end
|
19
|
-
|
20
19
|
end
|
21
20
|
|
22
21
|
def previous(attribute)
|
23
|
-
# self.changes[attribute.to_s][0]
|
24
|
-
# self.previous_version.try("display_#{attribute}") || self.previous_version.try(attribute)
|
25
22
|
self.try("previous_#{attribute}") || self.previous_version.try(attribute)
|
26
23
|
end
|
27
24
|
|
@@ -39,7 +36,6 @@ module Recorder
|
|
39
36
|
|
40
37
|
def next(attribute)
|
41
38
|
self.try("next_#{attribute}") || self.next_version.send(attribute)
|
42
|
-
# self.next_version.try("display_#{attribute}") || self.next_version.try(attribute)
|
43
39
|
end
|
44
40
|
|
45
41
|
def next_version
|
data/lib/recorder/observer.rb
CHANGED
data/lib/recorder/revision.rb
CHANGED
@@ -24,4 +24,32 @@ class Recorder::Revision < ActiveRecord::Base
|
|
24
24
|
validates :data, :presence => true
|
25
25
|
|
26
26
|
scope :ordered_by_created_at, -> { order(:created_at => :desc) }
|
27
|
+
|
28
|
+
def item_changeset
|
29
|
+
return @item_changeset if defined?(@item_changeset)
|
30
|
+
|
31
|
+
@item_changeset ||= self.changeset_klass(self.item).new(self.item, self.data['changes'])
|
32
|
+
end
|
33
|
+
|
34
|
+
def changed_associations
|
35
|
+
self.data['associations'].keys
|
36
|
+
end
|
37
|
+
|
38
|
+
def association_changeset(name)
|
39
|
+
association = self.item.send(name)
|
40
|
+
# association = association.source if association.decorated?
|
41
|
+
|
42
|
+
self.changeset_klass(association).new(association, self.data['associations'].fetch(name.to_s).try(:fetch, 'changes'))
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def changeset_klass(object)
|
48
|
+
klass = (defined?(Draper) && object.decorated?) ? object.source.class : object.class
|
49
|
+
klass = klass.base_class
|
50
|
+
klass = "#{klass}Changeset"
|
51
|
+
|
52
|
+
klass = klass.constantize rescue nil
|
53
|
+
klass.present? ? klass : Recorder::Changeset
|
54
|
+
end
|
27
55
|
end
|
data/lib/recorder/tape.rb
CHANGED
@@ -6,12 +6,23 @@ module Recorder
|
|
6
6
|
@item = item;
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def changes_for(event)
|
10
|
+
changes = case event.to_sym
|
11
|
+
when :create
|
12
|
+
self.sanitize_attributes(self.item.attributes)
|
13
|
+
when :update
|
14
|
+
self.sanitize_attributes(self.item.previous_changes)
|
15
|
+
when :destroy
|
16
|
+
self.sanitize_attributes(self.item.previous_changes)
|
17
|
+
else
|
18
|
+
raise ArgumentError
|
19
|
+
end
|
13
20
|
|
14
|
-
|
21
|
+
changes.any? ? { :changes => changes } : {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def record_create
|
25
|
+
data = self.changes_for(:create)
|
15
26
|
|
16
27
|
if data.any?
|
17
28
|
self.record(
|
@@ -24,12 +35,14 @@ module Recorder
|
|
24
35
|
end
|
25
36
|
|
26
37
|
def record_update
|
27
|
-
data = {
|
28
|
-
|
29
|
-
}
|
38
|
+
# data = {
|
39
|
+
# :changes => self.sanitize_attributes(self.item.previous_changes)
|
40
|
+
# }
|
30
41
|
|
31
|
-
|
32
|
-
|
42
|
+
data = self.changes_for(:update)
|
43
|
+
|
44
|
+
associations = self.parse_associations_attributes(:update)
|
45
|
+
data.merge!(:associations => self.parse_associations_attributes(:update)) if associations.any?
|
33
46
|
|
34
47
|
if data.any?
|
35
48
|
self.record(
|
@@ -55,10 +68,15 @@ module Recorder
|
|
55
68
|
end
|
56
69
|
|
57
70
|
def sanitize_attributes(attributes = {})
|
58
|
-
|
71
|
+
if self.item.recorder_options[:except].present?
|
72
|
+
except = Array.wrap(self.item.recorder_options[:except])
|
73
|
+
attributes.symbolize_keys.except(*except)
|
74
|
+
else
|
75
|
+
attributes
|
76
|
+
end
|
59
77
|
end
|
60
78
|
|
61
|
-
def parse_associations_attributes
|
79
|
+
def parse_associations_attributes(event)
|
62
80
|
if self.item.recorder_options[:associations].any?
|
63
81
|
self.item.recorder_options[:associations].inject({}) do |hash, association|
|
64
82
|
reflection = self.item.class.reflect_on_association(association)
|
@@ -66,13 +84,16 @@ module Recorder
|
|
66
84
|
if reflection.collection?
|
67
85
|
|
68
86
|
else
|
69
|
-
object = self.item.send(association)
|
70
|
-
|
71
|
-
|
72
|
-
hash[reflection.name] = {
|
73
|
-
:changes => self.sanitize_attributes(object.previous_changes)
|
74
|
-
}
|
87
|
+
if object = self.item.send(association)
|
88
|
+
changes = Recorder::Tape.new(object).changes_for(event)
|
89
|
+
hash[reflection.name] = changes if changes.any?
|
75
90
|
end
|
91
|
+
|
92
|
+
# if object.present? && self.sanitize_attributes(object.previous_changes).any?
|
93
|
+
# hash[reflection.name] = {
|
94
|
+
# :changes => self.sanitize_attributes(object.previous_changes)
|
95
|
+
# }
|
96
|
+
# end
|
76
97
|
end
|
77
98
|
end
|
78
99
|
|
data/lib/recorder/version.rb
CHANGED
data/lib/recorder.rb
CHANGED
@@ -25,20 +25,17 @@ module Recorder
|
|
25
25
|
@active_record_protected_attributes ||= !!defined?(ProtectedAttributes)
|
26
26
|
end
|
27
27
|
|
28
|
+
# Returns version of Recorder as +String+
|
29
|
+
def version
|
30
|
+
VERSION::STRING
|
31
|
+
end
|
32
|
+
|
28
33
|
# Thread-safe hash to hold Recorder's data.
|
29
34
|
# @api private
|
30
35
|
def store
|
31
36
|
RequestStore.store[:recorder] ||= { }
|
32
37
|
end
|
33
|
-
|
34
|
-
def version
|
35
|
-
VERSION::STRING
|
36
|
-
end
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
|
-
if defined?(Draper)
|
41
|
-
require 'recorder/draper/decorator_concern'
|
42
|
-
end
|
43
|
-
|
44
41
|
require 'recorder/revision'
|
data/recorder.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: recorder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Alexandrov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-07-
|
11
|
+
date: 2016-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -120,6 +120,20 @@ dependencies:
|
|
120
120
|
- - "~>"
|
121
121
|
- !ruby/object:Gem::Version
|
122
122
|
version: '3.0'
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: yard
|
125
|
+
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
type: :development
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
123
137
|
description: Recorder tracks changes of your Rails models
|
124
138
|
email:
|
125
139
|
- igor.alexandrov@jetrockets.ru
|
@@ -138,10 +152,11 @@ files:
|
|
138
152
|
- bin/setup
|
139
153
|
- lib/generators/recorder/USAGE
|
140
154
|
- lib/generators/recorder/install_generator.rb
|
155
|
+
- lib/generators/recorder/templates/add_index_by_user_id_to_recorder_revisions.rb
|
156
|
+
- lib/generators/recorder/templates/add_number_column_to_recorder_revisions.rb
|
141
157
|
- lib/generators/recorder/templates/create_recorder_revisions.rb
|
142
158
|
- lib/recorder.rb
|
143
159
|
- lib/recorder/changeset.rb
|
144
|
-
- lib/recorder/draper/decorator_concern.rb
|
145
160
|
- lib/recorder/observer.rb
|
146
161
|
- lib/recorder/rails/controller_concern.rb
|
147
162
|
- lib/recorder/revision.rb
|
@@ -173,3 +188,4 @@ signing_key:
|
|
173
188
|
specification_version: 4
|
174
189
|
summary: Rails model auditor
|
175
190
|
test_files: []
|
191
|
+
has_rdoc:
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module Recorder
|
2
|
-
module Draper
|
3
|
-
module DecoratorConcern
|
4
|
-
def self.included(base)
|
5
|
-
base.decorates_association :item
|
6
|
-
end
|
7
|
-
|
8
|
-
def item_changeset
|
9
|
-
return @item_changeset if defined?(@item_changeset)
|
10
|
-
|
11
|
-
@item_changeset ||= self.changeset_klass(self.item.source).new(self.item, source.data['changes'])
|
12
|
-
end
|
13
|
-
|
14
|
-
def changed_associations
|
15
|
-
source.data['associations'].keys
|
16
|
-
end
|
17
|
-
|
18
|
-
def association_changeset(name)
|
19
|
-
association = self.item.send(name)
|
20
|
-
# association = association.source if association.decorated?
|
21
|
-
|
22
|
-
self.changeset_klass(association).new(association, source.data['associations'].fetch(name.to_s).try(:fetch, 'changes'))
|
23
|
-
end
|
24
|
-
|
25
|
-
protected
|
26
|
-
|
27
|
-
def changeset_klass(object)
|
28
|
-
klass = object.decorated? ? object.source.class : object.class
|
29
|
-
klass = klass.base_class
|
30
|
-
klass = "#{klass}Changeset"
|
31
|
-
|
32
|
-
klass = klass.constantize rescue nil
|
33
|
-
klass.present? ? klass : Recorder::Changeset
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|