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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e701347d79260bff1bb8db40f220512a456720b66efa246de76dac9a9790bac2
4
- data.tar.gz: a8b56e341270752b63f5d1195232e0ac90972d3e66bf0368561b0775ea45e99d
3
+ metadata.gz: 5075dc703ff0a06e13b0ca7893c668bc7da0a60bc24032697ec8175d25ba6ce3
4
+ data.tar.gz: 6a5242a25eaa02ce127a6af099b58e708fe020b0dc17f2ffa3e603644e69b645
5
5
  SHA512:
6
- metadata.gz: 4991d4f6fb02cb56c5f3b952416fb2c58209eae7a84d65d8db9147b797cab1c40af9123d1be4e70a4b59a9d5a46247f7a1a913695558bf9d7641e76b1fcc38c0
7
- data.tar.gz: ccdd5e59e29546563dc5cbba93796682dcdb07286aa91da7974d544daa41a3d43724b93d749d41b7dd5e957240f08f0b9ca062e74e22242d4c22e727dc34e799
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
- [![CircleCI](https://circleci.com/gh/boxt/logga/tree/master.svg?style=svg&circle-token=f9550ac25744c292e3680638bad3d5deafb1c4e1)](https://circleci.com/gh/boxt/logga/tree/master)
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 this to your model:
34
+ Add the following to your model:
30
35
 
31
36
  ```ruby
32
- class Order < ApplicationRecord
33
- add_log_entries_for :create, :update
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 Order instance will be created whenever a new one is created or
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
- 2.1.2
1
+ 4.0.2
2
+
@@ -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 :log_fields, instance_writer: false
8
+ class_attribute :allowed_fields, instance_writer: false
12
9
  class_attribute :excluded_fields, instance_writer: false
13
- self.log_fields = {}
14
- self.excluded_fields = {}
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, to: :self, fields: {}, exclude_fields: [])
19
- after_create :log_model_creation if actions.include?(: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 :log_model_changes if actions.include?(: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.log_fields = fields
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
- create_log_entry(author_data.merge(body: body)) if body.present?
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 if should_not_log?
40
+ return unless should_log?
38
41
 
39
42
  body_generator = ->(record) { default_creation_log_body(record) }
40
- body = log_fields.fetch(:created_at, body_generator).call(self)
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 if should_not_log?
48
+ return unless should_log?
46
49
 
47
50
  body_generator = ->(record) { default_deletion_log_body(record) }
48
- body = log_fields.fetch(:deleted_at, body_generator).call(self)
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 if should_not_log?
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
- author_type: data[:type],
66
- author_name: data[:name]
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 << log_fields.fetch(field.to_sym, body_generator).call(self, field, old_value, new_value)
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
- EXCLUDED_KEYS.include?(key.to_sym) ||
109
- (!log_fields.include?(key.to_sym) &&
110
- (excluded_fields.include?(key.to_sym) ||
111
- EXCLUDED_KEYS_SUFFIXES.any? { |suffix| key.to_s.end_with?(suffix.to_s) }))
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 should_not_log?
115
- !log_receiver.respond_to?(:log_entries)
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)
@@ -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
- require_relative "logga/version"
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: 2.1.2
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: 2020-10-23 00:00:00.000000000 Z
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: '5.2'
20
- - - "~>"
19
+ version: '6'
20
+ - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '6.0'
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: '5.2'
30
- - - "~>"
29
+ version: '6'
30
+ - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '6.0'
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: '5.2'
40
- - - "~>"
39
+ version: '6'
40
+ - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: '6.0'
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: '5.2'
50
- - - "~>"
49
+ version: '6'
50
+ - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: '6.0'
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.5'
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.1.4
88
+ rubygems_version: 3.3.7
185
89
  signing_key:
186
90
  specification_version: 4
187
91
  summary: ActiveRecord log entries on model changes