logga 2.1.2 → 4.0.2
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 +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
|
-
[](https://badge.fury.io/rb/logga)
|
6
|
+
[](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
|