logga 2.1.2 → 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +82 -10
- data/VERSION +2 -1
- data/lib/logga/active_record.rb +42 -30
- data/lib/logga/config.rb +13 -0
- data/lib/logga.rb +27 -1
- metadata +19 -115
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5075dc703ff0a06e13b0ca7893c668bc7da0a60bc24032697ec8175d25ba6ce3
|
4
|
+
data.tar.gz: 6a5242a25eaa02ce127a6af099b58e708fe020b0dc17f2ffa3e603644e69b645
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '032693244e4731bf72f85c44a864da4b7b3c7ae8486fd05528ec499dc2768c41343d0e507864bd8807162e96ddad396cbc387228169357910dbc9ceaeb0d3912'
|
7
|
+
data.tar.gz: af16e0fafb5da9d8c2c7c9b88d2e4fec44d8e0508ba101f83a6d94ee7e0b3fadf8bff5624531b7ff6e5c2ac95effb831c396f80e1c78f31673bc4c9b0e28e871
|
data/README.md
CHANGED
@@ -2,7 +2,12 @@
|
|
2
2
|
|
3
3
|
Provides attribute logging functionality to ActiveRecord objects.
|
4
4
|
|
5
|
-
[![
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/logga.svg)](https://badge.fury.io/rb/logga)
|
6
|
+
[![CI](https://github.com/boxt/logga/actions/workflows/ci.yml/badge.svg)](https://github.com/boxt/logga/actions/workflows/ci.yml)
|
7
|
+
|
8
|
+
## Requirements
|
9
|
+
|
10
|
+
* Ruby 2.7 or above
|
6
11
|
|
7
12
|
## Installation
|
8
13
|
|
@@ -26,27 +31,94 @@ gem install logga
|
|
26
31
|
|
27
32
|
## Usage
|
28
33
|
|
29
|
-
Add
|
34
|
+
Add the following to your model:
|
30
35
|
|
31
36
|
```ruby
|
32
|
-
class
|
33
|
-
|
37
|
+
class Thing < ApplicationRecord
|
38
|
+
# Optional author accessor. See #author
|
39
|
+
attr_accessor :author
|
40
|
+
|
41
|
+
# Association to :log_entries, which the loggable object must response to for logging.
|
42
|
+
has_many :log_entries, as: :loggable, dependent: :destroy
|
43
|
+
|
44
|
+
add_log_entries_for(
|
45
|
+
:create, # Log on object create
|
46
|
+
:delete, # Log on object delete
|
47
|
+
:update, # Log on object update
|
48
|
+
allowed_fields: [], # set an array of fields allowed to be logged
|
49
|
+
exclude_fields: [], # set an array of fields excluded from logging. Ignored if allowed_fields is set
|
50
|
+
fields: {}, # Custom messages for fields. See #fields
|
51
|
+
to: nil
|
52
|
+
)
|
34
53
|
end
|
35
54
|
```
|
36
55
|
|
37
|
-
So that new LogEntry records attached to a given
|
56
|
+
So that new `LogEntry` records attached to a given `Thing` instance will be created whenever a new one is created or
|
38
57
|
modified.
|
39
58
|
|
59
|
+
## Author
|
60
|
+
|
61
|
+
If you want to log the author of the changes you can do so by setting:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
thing.author = { id: "1", name: "Barry", type: "User" }
|
65
|
+
```
|
66
|
+
|
67
|
+
## Fields
|
68
|
+
|
69
|
+
You can override the default messages per field by using:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
add_log_entries_for(
|
73
|
+
:update,
|
74
|
+
fields: {
|
75
|
+
name: lambda { |record, field, old_value, new_value|
|
76
|
+
"Name changed from #{old_value} to #{new_value}"
|
77
|
+
}
|
78
|
+
}
|
79
|
+
)
|
80
|
+
```
|
81
|
+
|
82
|
+
This is with the exeception on `:created_at` which only takes the created record.
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
add_log_entries_for(
|
86
|
+
:create,
|
87
|
+
fields: {
|
88
|
+
created_at: lambda { |record|
|
89
|
+
"Created object with id: #{record.id}"
|
90
|
+
}
|
91
|
+
}
|
92
|
+
)
|
93
|
+
```
|
94
|
+
|
95
|
+
## Configuration
|
96
|
+
|
97
|
+
Add an initializer to your project:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
Logga.configure do |config|
|
101
|
+
config.enabled = true
|
102
|
+
config.excluded_fields = [] # Default array of excluded fields i.e. [:id] to ignore all :id fields for every object
|
103
|
+
config.excluded_suffixes = [] # Array of excluded suffixes i.e. [:_id] to ignore all fields that end in :_id for every object
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
For example:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
Logga.configure do |config|
|
111
|
+
config.excluded_fields = [:id] # Don't log any id changes
|
112
|
+
config.excluded_suffixes = [_id] # Don't log any column that ends in _id
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
40
116
|
## Development
|
41
117
|
|
42
118
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
43
119
|
|
44
120
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
45
121
|
|
46
|
-
## Versioning
|
47
|
-
|
48
|
-
The version of the gem should be set in the `VERSION` file found in the root of the project. This is then read by the `lib/boxt_aasm_ext/version.rb` file to set in the gem.
|
49
|
-
|
50
122
|
## Contributing
|
51
123
|
|
52
124
|
Bug reports and pull requests are welcome on GitHub at https://github.com/boxt/logga.
|
@@ -57,5 +129,5 @@ The gem is available as open source under the terms of the [MIT License](http://
|
|
57
129
|
|
58
130
|
## TODOs
|
59
131
|
|
60
|
-
- Write some tests
|
61
132
|
- Improve the documentation
|
133
|
+
- Add migration generator for `:log_entries`
|
data/VERSION
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
4.0.2
|
2
|
+
|
data/lib/logga/active_record.rb
CHANGED
@@ -4,25 +4,26 @@ module Logga
|
|
4
4
|
module ActiveRecord
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
EXCLUDED_KEYS = %i[id created_at deleted_at initial updated_at log sent_after_sales_emails].freeze
|
8
|
-
EXCLUDED_KEYS_SUFFIXES = %i[_id _filenames].freeze
|
9
|
-
|
10
7
|
included do
|
11
|
-
class_attribute :
|
8
|
+
class_attribute :allowed_fields, instance_writer: false
|
12
9
|
class_attribute :excluded_fields, instance_writer: false
|
13
|
-
|
14
|
-
|
10
|
+
class_attribute :fields, instance_writer: false
|
11
|
+
|
12
|
+
self.allowed_fields = []
|
13
|
+
self.excluded_fields = []
|
14
|
+
self.fields = {}
|
15
15
|
end
|
16
16
|
|
17
17
|
class_methods do
|
18
|
-
def add_log_entries_for(*actions,
|
19
|
-
after_create
|
18
|
+
def add_log_entries_for(*actions, allowed_fields: [], exclude_fields: [], fields: {}, to: :self)
|
19
|
+
after_create :log_model_creation if actions.include?(:create)
|
20
20
|
after_destroy :log_model_deletion if actions.include?(:delete)
|
21
|
-
after_update
|
21
|
+
after_update :log_model_changes if actions.include?(:update)
|
22
22
|
define_method(:log_receiver) { to == :self ? self : send(to) }
|
23
23
|
|
24
|
-
self.
|
25
|
-
self.excluded_fields = Array(exclude_fields)
|
24
|
+
self.allowed_fields = Array(allowed_fields)
|
25
|
+
self.excluded_fields = allowed_fields.blank? ? Array(exclude_fields) : []
|
26
|
+
self.fields = fields
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
@@ -30,27 +31,29 @@ module Logga
|
|
30
31
|
return if changes.blank?
|
31
32
|
|
32
33
|
body = field_changes_to_message(changes)
|
33
|
-
|
34
|
+
return if body.blank?
|
35
|
+
|
36
|
+
create_log_entry(author_data.merge(body: body))
|
34
37
|
end
|
35
38
|
|
36
39
|
def log_model_creation
|
37
|
-
return
|
40
|
+
return unless should_log?
|
38
41
|
|
39
42
|
body_generator = ->(record) { default_creation_log_body(record) }
|
40
|
-
body =
|
43
|
+
body = fields.fetch(:created_at, body_generator).call(self)
|
41
44
|
create_log_entry(author_data.merge(body: body, created_at: creation_at))
|
42
45
|
end
|
43
46
|
|
44
47
|
def log_model_deletion
|
45
|
-
return
|
48
|
+
return unless should_log?
|
46
49
|
|
47
50
|
body_generator = ->(record) { default_deletion_log_body(record) }
|
48
|
-
body =
|
51
|
+
body = fields.fetch(:deleted_at, body_generator).call(self)
|
49
52
|
create_log_entry(author_data.merge(body: body))
|
50
53
|
end
|
51
54
|
|
52
55
|
def log_model_changes
|
53
|
-
return
|
56
|
+
return unless should_log?
|
54
57
|
|
55
58
|
field_changes = previous_changes.reject { |k, _| reject_change?(k) }
|
56
59
|
log_field_changes(field_changes)
|
@@ -60,13 +63,22 @@ module Logga
|
|
60
63
|
|
61
64
|
def author_data
|
62
65
|
data = Hash(log_receiver.try(:author) || try(:author)).with_indifferent_access
|
66
|
+
|
63
67
|
{
|
64
68
|
author_id: data[:id],
|
65
|
-
|
66
|
-
|
69
|
+
author_name: data[:name],
|
70
|
+
author_type: data[:type]
|
67
71
|
}
|
68
72
|
end
|
69
73
|
|
74
|
+
def config_excluded_fields
|
75
|
+
Logga.configuration.excluded_fields
|
76
|
+
end
|
77
|
+
|
78
|
+
def config_excluded_suffixes
|
79
|
+
Logga.configuration.excluded_suffixes
|
80
|
+
end
|
81
|
+
|
70
82
|
def create_log_entry(entry)
|
71
83
|
log_receiver&.log_entries&.create(entry)
|
72
84
|
end
|
@@ -78,10 +90,7 @@ module Logga
|
|
78
90
|
end
|
79
91
|
|
80
92
|
def default_creation_log_body(record)
|
81
|
-
|
82
|
-
"#{titleized_model_class_name(record)} created",
|
83
|
-
("(#{record.state})" if record.try(:state))
|
84
|
-
].compact.join(" ")
|
93
|
+
"#{titleized_model_class_name(record)} created"
|
85
94
|
end
|
86
95
|
|
87
96
|
def default_change_log_body(record, field, _old_value, new_value)
|
@@ -100,19 +109,22 @@ module Logga
|
|
100
109
|
default_change_log_body(record, field, old_value, new_value)
|
101
110
|
}
|
102
111
|
changes.inject([]) do |result, (field, (old_value, new_value))|
|
103
|
-
result <<
|
112
|
+
result << fields.fetch(field.to_sym, body_generator).call(self, field, old_value, new_value)
|
104
113
|
end.compact.join("\n")
|
105
114
|
end
|
106
115
|
|
107
116
|
def reject_change?(key)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
117
|
+
sym_key = key.to_sym
|
118
|
+
return allowed_fields.exclude?(sym_key) if allowed_fields.present?
|
119
|
+
|
120
|
+
config_excluded_fields.include?(sym_key) ||
|
121
|
+
(fields.exclude?(sym_key) &&
|
122
|
+
(excluded_fields.include?(sym_key) ||
|
123
|
+
config_excluded_suffixes.any? { |suffix| key.to_s.end_with?(suffix.to_s) }))
|
112
124
|
end
|
113
125
|
|
114
|
-
def
|
115
|
-
|
126
|
+
def should_log?
|
127
|
+
Logga.enabled? && log_receiver.respond_to?(:log_entries)
|
116
128
|
end
|
117
129
|
|
118
130
|
def titleized_model_class_name(record)
|
data/lib/logga/config.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Logga
|
4
|
+
class Config
|
5
|
+
attr_accessor :enabled, :excluded_fields, :excluded_suffixes
|
6
|
+
|
7
|
+
def initialize(enabled: true, excluded_fields: [], excluded_suffixes: [])
|
8
|
+
@enabled = enabled
|
9
|
+
@excluded_fields = excluded_fields
|
10
|
+
@excluded_suffixes = excluded_suffixes
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/logga.rb
CHANGED
@@ -3,11 +3,37 @@
|
|
3
3
|
require "active_support"
|
4
4
|
require "active_support/core_ext"
|
5
5
|
require "active_support/concern"
|
6
|
-
|
6
|
+
|
7
7
|
require_relative "logga/active_record"
|
8
|
+
require_relative "logga/config"
|
9
|
+
require_relative "logga/version"
|
8
10
|
|
9
11
|
module Logga
|
10
12
|
ActiveSupport.on_load(:active_record) do
|
11
13
|
include Logga::ActiveRecord
|
12
14
|
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def configuration
|
18
|
+
@configuration ||= Config.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure
|
22
|
+
yield(configuration)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Switches Logga on or off
|
26
|
+
def enabled=(value)
|
27
|
+
configuration.enabled = value
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns `true` if Logga is on, `false` otherwise
|
31
|
+
def enabled?
|
32
|
+
!!configuration.enabled
|
33
|
+
end
|
34
|
+
|
35
|
+
def version
|
36
|
+
Logga::VERSION
|
37
|
+
end
|
38
|
+
end
|
13
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logga
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boxt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,138 +16,40 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
- - "
|
19
|
+
version: '6'
|
20
|
+
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '8'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
30
|
-
- - "
|
29
|
+
version: '6'
|
30
|
+
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '8'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: activesupport
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
40
|
-
- - "
|
39
|
+
version: '6'
|
40
|
+
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: '
|
42
|
+
version: '8'
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: '
|
50
|
-
- - "
|
49
|
+
version: '6'
|
50
|
+
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: '
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: boxt_ruby_style_guide
|
55
|
-
requirement: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - '='
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: 7.2.0
|
60
|
-
type: :development
|
61
|
-
prerelease: false
|
62
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
requirements:
|
64
|
-
- - '='
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: 7.2.0
|
67
|
-
- !ruby/object:Gem::Dependency
|
68
|
-
name: bundler
|
69
|
-
requirement: !ruby/object:Gem::Requirement
|
70
|
-
requirements:
|
71
|
-
- - "~>"
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
version: '2.1'
|
74
|
-
type: :development
|
75
|
-
prerelease: false
|
76
|
-
version_requirements: !ruby/object:Gem::Requirement
|
77
|
-
requirements:
|
78
|
-
- - "~>"
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
version: '2.1'
|
81
|
-
- !ruby/object:Gem::Dependency
|
82
|
-
name: byebug
|
83
|
-
requirement: !ruby/object:Gem::Requirement
|
84
|
-
requirements:
|
85
|
-
- - "~>"
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
version: '11.0'
|
88
|
-
type: :development
|
89
|
-
prerelease: false
|
90
|
-
version_requirements: !ruby/object:Gem::Requirement
|
91
|
-
requirements:
|
92
|
-
- - "~>"
|
93
|
-
- !ruby/object:Gem::Version
|
94
|
-
version: '11.0'
|
95
|
-
- !ruby/object:Gem::Dependency
|
96
|
-
name: rake
|
97
|
-
requirement: !ruby/object:Gem::Requirement
|
98
|
-
requirements:
|
99
|
-
- - "~>"
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: '13.0'
|
102
|
-
type: :development
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
requirements:
|
106
|
-
- - "~>"
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
version: '13.0'
|
109
|
-
- !ruby/object:Gem::Dependency
|
110
|
-
name: rspec
|
111
|
-
requirement: !ruby/object:Gem::Requirement
|
112
|
-
requirements:
|
113
|
-
- - "~>"
|
114
|
-
- !ruby/object:Gem::Version
|
115
|
-
version: '3.9'
|
116
|
-
type: :development
|
117
|
-
prerelease: false
|
118
|
-
version_requirements: !ruby/object:Gem::Requirement
|
119
|
-
requirements:
|
120
|
-
- - "~>"
|
121
|
-
- !ruby/object:Gem::Version
|
122
|
-
version: '3.9'
|
123
|
-
- !ruby/object:Gem::Dependency
|
124
|
-
name: rspec-nc
|
125
|
-
requirement: !ruby/object:Gem::Requirement
|
126
|
-
requirements:
|
127
|
-
- - "~>"
|
128
|
-
- !ruby/object:Gem::Version
|
129
|
-
version: '0.3'
|
130
|
-
type: :development
|
131
|
-
prerelease: false
|
132
|
-
version_requirements: !ruby/object:Gem::Requirement
|
133
|
-
requirements:
|
134
|
-
- - "~>"
|
135
|
-
- !ruby/object:Gem::Version
|
136
|
-
version: '0.3'
|
137
|
-
- !ruby/object:Gem::Dependency
|
138
|
-
name: simplecov
|
139
|
-
requirement: !ruby/object:Gem::Requirement
|
140
|
-
requirements:
|
141
|
-
- - "~>"
|
142
|
-
- !ruby/object:Gem::Version
|
143
|
-
version: '0.17'
|
144
|
-
type: :development
|
145
|
-
prerelease: false
|
146
|
-
version_requirements: !ruby/object:Gem::Requirement
|
147
|
-
requirements:
|
148
|
-
- - "~>"
|
149
|
-
- !ruby/object:Gem::Version
|
150
|
-
version: '0.17'
|
52
|
+
version: '8'
|
151
53
|
description: Extensions to ActiveRecord to log entries on model changes
|
152
54
|
email:
|
153
55
|
- developers@boxt.co.uk
|
@@ -161,11 +63,13 @@ files:
|
|
161
63
|
- VERSION
|
162
64
|
- lib/logga.rb
|
163
65
|
- lib/logga/active_record.rb
|
66
|
+
- lib/logga/config.rb
|
164
67
|
- lib/logga/version.rb
|
165
68
|
homepage: https://github.com/boxt/logga
|
166
69
|
licenses:
|
167
70
|
- MIT
|
168
|
-
metadata:
|
71
|
+
metadata:
|
72
|
+
rubygems_mfa_required: 'true'
|
169
73
|
post_install_message:
|
170
74
|
rdoc_options: []
|
171
75
|
require_paths:
|
@@ -174,14 +78,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
174
78
|
requirements:
|
175
79
|
- - ">="
|
176
80
|
- !ruby/object:Gem::Version
|
177
|
-
version: '2.
|
81
|
+
version: '2.7'
|
178
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
83
|
requirements:
|
180
84
|
- - ">="
|
181
85
|
- !ruby/object:Gem::Version
|
182
86
|
version: '0'
|
183
87
|
requirements: []
|
184
|
-
rubygems_version: 3.
|
88
|
+
rubygems_version: 3.3.7
|
185
89
|
signing_key:
|
186
90
|
specification_version: 4
|
187
91
|
summary: ActiveRecord log entries on model changes
|