rails_log_book 0.3.0 → 1.0.0

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
- SHA1:
3
- metadata.gz: 1dcd95f53c62fb9971f9b6aa3600f083fe20e390
4
- data.tar.gz: 5c8d602213701f68f25b4ea419bba3b415e25f4b
2
+ SHA256:
3
+ metadata.gz: 33c84201892d61f332f7f60bd66ac9d052c37b9d9a894e5210eecf528efcb1ee
4
+ data.tar.gz: 2dd8618869a1a1955e8c24261edbd11561662792d39e736de94513ea32b28358
5
5
  SHA512:
6
- metadata.gz: cf696b59c7b89efea1dbb24525750653d1507e3b78803a4ae2c36076348f73d9099210ba75ad54c2f5f8f79d90cf7d2792f4d12becff5f5ba6867198991aebf5
7
- data.tar.gz: 70d8ddd9694e9221d4347e1aaaaa5ceb8859cab8a0d224bca164bb1e989e4643956710ac216b2717fc05ff749fd37ed6f8708f7e6622f723aea8bd53da127634
6
+ metadata.gz: 1f0b026c941e50454283953976c11eef81cba06e8c37ddb6ffaffbfb1ca1c3ef030c1b6e82c5be68c9151948465fa335ae4f3b79a8e2606a4a0190559e6f07cd
7
+ data.tar.gz: 0b321da7a85b6fe8620fe1863ac26560c3dd40a5fa06eabf1a7d4d1ec0f299d296994634370bac9c66a82990440ae2d578ced623b617474d2f864ec8b6443bde
data/README.md CHANGED
@@ -1,29 +1,185 @@
1
1
  # LogBook
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/log_book`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ LogBook is a gem that tracks changes on your records. Created for the purpuse of auditing and showing activity log.
4
+ For comparison with [paper_\__trail](https://github.com/airblade/paper_trail) and [audited](https://github.com/collectiveidea/audited) see []()
4
5
 
5
- TODO: Delete this and the text above, and describe your gem
6
+ ## Supported ORMs
6
7
 
7
- ## Installation
8
+ Currently only supports ActiveRecord.
8
9
 
9
- Add this line to your application's Gemfile:
10
+ ## Instalation
11
+
12
+ Add to your Gemfile:
13
+
14
+ ``` ruby
15
+ gem 'rails_log_book'
16
+ ```
17
+
18
+ Then run:
10
19
 
11
20
  ```ruby
12
- gem 'log_book'
21
+ rails generate log_book:install
22
+ rake db:migrate
13
23
  ```
14
24
 
15
- And then execute:
25
+ ## Usage
16
26
 
17
- $ bundle
27
+ Add to models you want to keep track of:
18
28
 
19
- Or install it yourself as:
29
+ ``` ruby
30
+ class User < ActiveRecord::Base
31
+ include LogBook::Recorder
20
32
 
21
- $ gem install log_book
33
+ has_log_book_records
34
+ end
35
+ ```
22
36
 
23
- ## Usage
37
+ Add to controlers and actions you want the tracker to be active:
38
+
39
+ ``` ruby
40
+ class UsersController < ApplicationController
41
+ include LogBook::ControllerRecord
42
+ end
43
+ ```
44
+
45
+ By default, whenever a user record is created, updated or deleted in any actions of users\_controller a new log\_book record will be created.
46
+
47
+ ## ActiveRecord Options
48
+
49
+ ### fields
50
+
51
+ ``` ruby
52
+ class User < ActiveRecord::Base
53
+ include LogBook::Recorder
54
+
55
+ # all fields
56
+ # has_log_book_records
24
57
 
25
- TODO: Write usage instructions here
58
+ # Only fields
59
+ # has_log_book_records only: [:email, :name]
60
+
61
+ # Ignored fields
62
+ # has_log_book_records except: [:password]
63
+
64
+ # Default ignored fields
65
+ # primary_key (id), LogBook.config.ignored_attributes (:created_at, :updated_at)
66
+ end
67
+ ```
68
+
69
+ ### callbacks
70
+
71
+ ``` ruby
72
+ class User < ActiveRecord::Base
73
+ include LogBook::Recorder
74
+
75
+ # all events
76
+ # has_log_book_records
77
+
78
+ # Only record on create and destroy (not update)
79
+ # has_log_book_records on: [:create, :destroy]
80
+ end
81
+ ```
82
+
83
+ ### parent
84
+
85
+ Define who is a parent of this object. Will be recorded in a `parent` polymorphic columns
86
+
87
+ ``` ruby
88
+ class User < ActiveRecord::Base
89
+ include LogBook::Recorder
90
+ belongs_to :company
91
+
92
+ # Parent is Company and will be recorded with each user change
93
+ # has_log_book_records parent: :company
94
+ end
95
+ ```
26
96
 
97
+ ### meta
98
+
99
+ Arbitrary column. This is a jsonb field which can have all kinds of information. Useful when you want to cache fields at the exact point of record creation
100
+
101
+ ``` ruby
102
+ class User < ActiveRecord::Base
103
+ include LogBook::Recorder
104
+
105
+ # runs `log_book_meta(record)` method to assign to `:meta` field
106
+ # has_log_book_records meta: true
107
+
108
+ # runs `meta_method` method to assing to `:meta` field
109
+ # has_log_book_records meta: :meta_method
110
+
111
+ # runs passed proc to assing to `:meta` field
112
+ # has_log_book_records meta: -> { { slug: email.split('@').first } }
113
+ end
114
+ ```
115
+
116
+ ### squash
117
+
118
+ Enables/disables suashing on this model
119
+
120
+ ``` ruby
121
+ class User < ActiveRecord::Base
122
+ include LogBook::Recorder
123
+
124
+ # Enables squashing (defaults to false)
125
+ # has_log_book_records squash: true
126
+ ```
127
+
128
+ ## ActionController options
129
+
130
+ ### current\_author
131
+
132
+ Defines what method is run when looking for the author for recording
133
+
134
+ ``` ruby
135
+ class Admin::UsersController < ActionController::Base
136
+ inlcude LogBook::ControllerRecord
137
+
138
+ # defaults to `current_user`
139
+ def current_author
140
+ current_admin
141
+ end
142
+ ```
143
+
144
+ ## Configuration
145
+
146
+ ``` ruby
147
+ # config/initializers/log_book.rb
148
+ LogBook.configure do |config|
149
+ config.records_table_name = 'records'
150
+ config.ignored_attributes = [:updated_at, :created_at]
151
+ config.author_method = :current_user
152
+ config.record_squashing = false
153
+ config.recording_enabled = false
154
+ config.skip_if_empty_actions = [:update]
155
+ end
156
+ ```
157
+
158
+ ## Additional methods
159
+
160
+ ``` ruby
161
+ LogBook.with_recording {} #=> Enables recording within block
162
+ LogBook.without_recording {} #=> Disables recording within block
163
+ LogBook.record_as(author) {} #=> Records as a different author within block
164
+ LogBook.with_record_squashing {} #=> Squashes records within block
165
+ LogBook.enable_recording #=> Enables recording from this point
166
+ LogBook.disable_recording #=> Disables recording from this point
167
+ LogBook.record_squashing_enabled #=> Enables record squashing from this point
168
+ LogBook.recording_enabled #=> Returns true if recording is enabled
169
+ LogBook.recording_enabled=(val) #=> Enables/Disables recording
170
+ LogBook.squash_records #=> Squash records with current :request_uuid
171
+ ```
172
+
173
+ ## Squashing
174
+
175
+ The idea of squashing came when we needed to show an activity page where all changes made in the single request as one change.
176
+
177
+ Each request has its own unique `request_uuid` and it is recorded with each record. If squashing is enabled, `after_action` method with squashing is called.
178
+ All records with the same `request_uuid` are "squashed" into one record.
179
+
180
+ ``` sql
181
+ INSERT INTO "users" ("name", "email") VALUES ("test", "test@test.com")
182
+ ```
27
183
  ## Development
28
184
 
29
185
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -32,7 +188,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
188
 
33
189
  ## Contributing
34
190
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/log_book. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
191
+ Bug reports and pull requests are welcome on GitHub at https://github.com/infinum/log_book. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
192
 
37
193
 
38
194
  ## License
@@ -1,6 +1,6 @@
1
1
  require 'rails/generators/migration'
2
2
  require 'generators/log_book/migration'
3
- require 'log_book'
3
+ require 'rails_log_book'
4
4
 
5
5
  module LogBook
6
6
  module Generators
@@ -17,6 +17,12 @@ module LogBook
17
17
  def copy_migration
18
18
  migration_template 'install.rb', 'db/migrate/install_log_book.rb'
19
19
  end
20
+
21
+ def migration_version
22
+ if rails5?
23
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
24
+ end
25
+ end
20
26
  end
21
27
  end
22
28
  end
@@ -1,4 +1,4 @@
1
- class <%= migration_class_name %> < ActiveRecord::Migration
1
+ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
3
  create_table :records do |t|
4
4
  t.belongs_to :author, polymorphic: true, index: true
@@ -6,7 +6,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration
6
6
  t.belongs_to :parent, polymorphic: true, index: true
7
7
  t.jsonb :record_changes, default: {}
8
8
  t.jsonb :meta, default: {}
9
- t.string :request_uuid
9
+ t.string :request_uuid, index: true
10
10
  t.string :action
11
11
 
12
12
  t.datetime :created_at
@@ -21,7 +21,7 @@ module LogBook
21
21
  end
22
22
 
23
23
  def current_author
24
- raise NotImplementedError unless respond_to?(LogBook.config.author_method)
24
+ raise NotImplementedError unless respond_to?(LogBook.config.author_method, true)
25
25
  send(LogBook.config.author_method)
26
26
  end
27
27
  end
@@ -34,19 +34,6 @@ module LogBook
34
34
  self.class.with_recording(&block)
35
35
  end
36
36
 
37
- def new_record
38
- record = LogBook::Record.new(
39
- action: LogBook.store[:action],
40
- record_changes: record_changes,
41
- author: LogBook.store[:author],
42
- subject: self,
43
- meta: {}
44
- )
45
- record.meta = log_book_meta_info(record) if recording_options[:meta].present?
46
- record.parent = send(recording_options[:parent]) if recording_options[:parent].present?
47
- record
48
- end
49
-
50
37
  def recording_attributes
51
38
  attributes.except(*non_recording_columns)
52
39
  end
@@ -60,9 +47,9 @@ module LogBook
60
47
  def record_changes
61
48
  if recording_options[:only]
62
49
  recording_columns = self.class.recording_columns.map(&:name)
63
- changes.slice(*recording_columns)
50
+ saved_changes.slice(*recording_columns)
64
51
  else
65
- changes.except(*non_recording_columns)
52
+ saved_changes.except(*non_recording_columns)
66
53
  end
67
54
  end
68
55
 
@@ -80,12 +67,24 @@ module LogBook
80
67
 
81
68
  def write_record(action)
82
69
  return unless LogBook.recording_enabled
83
- LogBook.store[:action] ||= action
84
- record = new_record
70
+ record = new_record(LogBook.store[:action] || action)
85
71
  return unless record.changes_to_record?
86
72
  record.save
87
73
  end
88
74
 
75
+ def new_record(action)
76
+ record = LogBook::Record.new(
77
+ action: action,
78
+ record_changes: record_changes,
79
+ author: LogBook.store[:author],
80
+ subject: self,
81
+ meta: {}
82
+ )
83
+ record.meta = log_book_meta_info(record) if recording_options[:meta].present?
84
+ record.parent = send(recording_options[:parent]) if recording_options[:parent].present?
85
+ record
86
+ end
87
+
89
88
  def log_book_meta_info(record)
90
89
  case recording_options[:meta]
91
90
  when NilClass then nil
@@ -6,17 +6,28 @@ module LogBook
6
6
 
7
7
  def call
8
8
  records.group_by(&:parent).each do |parent, children|
9
- next if parent.nil?
10
9
  children_to_squash = children.select { |child| child.subject.try(:to_squash?) }
11
10
  next if children_to_squash.empty?
12
11
 
13
- parent_in_records = parent_in_records(parent)
14
- parent_in_records.record_changes.merge!(squashed_changes(children_to_squash, :record_changes))
15
- parent_in_records.meta.merge!(squashed_changes(children_to_squash, :meta))
16
- parent_in_records.created_at ||= children_to_squash.first.created_at
17
- parent_in_records.save
12
+ if parent.present?
13
+ parent_in_records = parent_in_records(parent)
14
+ parent_in_records.record_changes.merge!(squashed_changes(children_to_squash, :record_changes))
15
+ parent_in_records.meta.merge!(squashed_changes(children_to_squash, :meta))
16
+ parent_in_records.created_at ||= children_to_squash.first.created_at
17
+ parent_in_records.save
18
18
 
19
- children_to_squash.each(&:delete)
19
+ children_to_squash.each(&:delete)
20
+ else
21
+ next if children_to_squash.one?
22
+
23
+ records.reduce do |main_record, record|
24
+ main_record.record_changes.merge!(record.record_changes)
25
+ main_record.meta.merge!(record.meta)
26
+
27
+ record.delete
28
+ main_record
29
+ end.save
30
+ end
20
31
  end
21
32
  end
22
33
 
@@ -1,3 +1,3 @@
1
1
  module LogBook
2
- VERSION = "0.3.0"
2
+ VERSION = '1.0.0'
3
3
  end
data/log_book.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |spec|
6
6
  spec.name = 'rails_log_book'
7
7
  spec.version = LogBook::VERSION
8
8
  spec.authors = ['Stjepan Hadjic']
9
- spec.email = ['d4be4st@gmail.com']
9
+ spec.email = ['stjepan.hadjic@infinum.co']
10
10
 
11
11
  spec.summary = 'Write a short summary, because Rubygems requires one.'
12
12
  spec.description = 'Write a longer description or delete this line.'
@@ -32,5 +32,5 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'pry-byebug'
33
33
 
34
34
  spec.add_dependency 'request_store'
35
- spec.add_dependency 'activerecord', '>= 4.0', '< 5.1'
35
+ spec.add_dependency 'activerecord', '> 5.2'
36
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_log_book
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stjepan Hadjic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-18 00:00:00.000000000 Z
11
+ date: 2018-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -112,25 +112,19 @@ dependencies:
112
112
  name: activerecord
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '4.0'
118
- - - "<"
115
+ - - ">"
119
116
  - !ruby/object:Gem::Version
120
- version: '5.1'
117
+ version: '5.2'
121
118
  type: :runtime
122
119
  prerelease: false
123
120
  version_requirements: !ruby/object:Gem::Requirement
124
121
  requirements:
125
- - - ">="
126
- - !ruby/object:Gem::Version
127
- version: '4.0'
128
- - - "<"
122
+ - - ">"
129
123
  - !ruby/object:Gem::Version
130
- version: '5.1'
124
+ version: '5.2'
131
125
  description: Write a longer description or delete this line.
132
126
  email:
133
- - d4be4st@gmail.com
127
+ - stjepan.hadjic@infinum.co
134
128
  executables: []
135
129
  extensions: []
136
130
  extra_rdoc_files: []
@@ -180,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
174
  version: '0'
181
175
  requirements: []
182
176
  rubyforge_project:
183
- rubygems_version: 2.5.1
177
+ rubygems_version: 2.7.3
184
178
  signing_key:
185
179
  specification_version: 4
186
180
  summary: Write a short summary, because Rubygems requires one.