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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 99e7c1bf50c6c1844ee0961756ffe1ab06128991
4
- data.tar.gz: 51d81209e457c6d099f3ffb168ac261bcf559aed
3
+ metadata.gz: b4550b7a532edd1f5ce2c56036803a96ca4f8242
4
+ data.tar.gz: 4051cdb776fe3d7c25ad879547cd56dae3ae35ac
5
5
  SHA512:
6
- metadata.gz: f0d3fc8fb50bbb4bb2d87ad02cb2086669e6cced785e65a96a4f911a1ec6e33d0a4dcf81feecdc8bf6299e9fefe8601ae5fd54845f9ce0c8a100f256b26d278b
7
- data.tar.gz: 4812c0ac7f9c24fb614f7eb9f038c42ab57b5a732e319674d89ad87fe374fb4dd513077a881330e3a496859a7f3d1677ee1108c0818c3c3829d064a051d734d1
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 for `revisions` table"
15
+ desc: "Create partitions to `recorder_revisions` table"
16
16
  )
17
17
 
18
- desc "Generates (but does not run) a migration to add a `revisions` table."
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('add_partitions_to_recorder_revisions_table') if options.with_partitions?
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,6 @@
1
+ # This migration adds number column to the `revisions` table.
2
+ class AddIndexByUserIdToRecorderRevisions < ActiveRecord::Migration
3
+ def up
4
+ add_index :recorder_revisions, :user_id
5
+ end
6
+ end
@@ -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
@@ -1,4 +1,4 @@
1
- # This migration creates the `revisions` table.
1
+ # This migration creates the `recorder_revisions` table.
2
2
  class CreateRecorderRevisions < ActiveRecord::Migration
3
3
  def change
4
4
  create_table :recorder_revisions do |t|
@@ -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
@@ -11,7 +11,7 @@ module Recorder
11
11
 
12
12
  module ClassMethods
13
13
  def recorder(options = {})
14
- define_method 'recorder_option' do
14
+ define_method 'recorder_options' do
15
15
  options
16
16
  end
17
17
 
@@ -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 record_create
10
- data = {
11
- :changes => self.sanitize_attributes(self.item.attributes)
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
- # changes.merge!(self.parse_associations_attributes)
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
- :changes => self.sanitize_attributes(self.item.previous_changes)
29
- }
38
+ # data = {
39
+ # :changes => self.sanitize_attributes(self.item.previous_changes)
40
+ # }
30
41
 
31
- associations = self.parse_associations_attributes
32
- data.merge!(:associations => self.parse_associations_attributes) if associations.any?
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
- attributes.symbolize_keys.except(self.item.recorder_options[:except])
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
- if object.present? && self.sanitize_attributes(object.previous_changes).any?
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
 
@@ -3,7 +3,7 @@ module Recorder
3
3
  module VERSION
4
4
  MAJOR = 0
5
5
  MINOR = 1
6
- TINY = 3
6
+ TINY = 4
7
7
  PRE = nil
8
8
 
9
9
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".").freeze
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
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "bundler", "~> 1.11"
28
28
  spec.add_development_dependency "rake", "~> 10.0"
29
29
  spec.add_development_dependency "rspec", "~> 3.0"
30
+ spec.add_development_dependency 'yard'
30
31
  end
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.3
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-07 00:00:00.000000000 Z
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