omg-audit-group 0.1.2 → 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 +4 -4
- data/lib/audit_group.rb +95 -14
- metadata +11 -18
- data/.gitignore +0 -12
- data/.rspec +0 -3
- data/README.md +0 -98
- data/Rakefile +0 -17
- data/audit_group.gemspec +0 -33
- data/spec/audit_group_spec.rb +0 -108
- data/spec/spec_helper.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2103693c9d639bfce07ecae254b8df32a5571ed8084a141aa3b7d072ea62632
|
4
|
+
data.tar.gz: 8b49dfc610cacdf906fa910414064ad4cec032a14809512111e22c3f290c5e38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11d2bd4799f4680ca1b20487e64cd90292a2993c3741bceaa4301fc2adc273de765a346360fbc35268f078b18a334256571f59e7898b227918c4ef743a2aff57
|
7
|
+
data.tar.gz: 910a307b97833b1542ec839bb9b20c5cbc9732bbeb316accd78140a8e7d102894240ddf2e3227cbc2ee8e79172514eecf07048863dbd579cec120ee02deeb22c
|
data/lib/audit_group.rb
CHANGED
@@ -1,60 +1,141 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/all'
|
4
3
|
require 'audited'
|
5
4
|
|
6
5
|
class AuditGroup
|
7
|
-
VERSION = '0.1.
|
6
|
+
VERSION = '0.1.4'
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
class LockError < StandardError
|
9
|
+
def initialize
|
10
|
+
super('Request is locked and cannot be run again. If you want to add operations to an existing request_uuid, create a new instance')
|
11
|
+
end
|
12
|
+
end
|
12
13
|
|
13
14
|
class << self
|
14
15
|
attr_accessor :current
|
15
16
|
|
16
|
-
|
17
|
-
|
17
|
+
##
|
18
|
+
# Updates `audited` gem to make every operation use the same `request_uuid`.
|
19
|
+
#
|
20
|
+
# @param request_uuid [String] The `request_uuid` to use for all operations within the block.
|
18
21
|
def set_request_uuid(request_uuid = SecureRandom.uuid)
|
19
22
|
Audited.store[:current_request_uuid] = request_uuid
|
20
23
|
end
|
21
24
|
|
25
|
+
##
|
26
|
+
# Resets `audited` gem to generate a new `request_uuid` for each operation.
|
22
27
|
def unset_request_uuid
|
23
28
|
Audited.store.delete(:current_request_uuid)
|
24
29
|
end
|
25
30
|
|
31
|
+
##
|
32
|
+
# Clears out any current `request_uuid` or AuditGroup request.
|
26
33
|
def reset
|
27
34
|
unset_request_uuid
|
28
35
|
@current = nil
|
29
36
|
end
|
30
37
|
|
31
|
-
|
32
|
-
|
38
|
+
##
|
39
|
+
# Creates a new AuditGroup and runs operations to be all given the same `request_uuid`
|
40
|
+
#
|
41
|
+
# @yield operations whose audits should be associated with the same request_uuid.
|
42
|
+
def request(dry_run: false, &block)
|
43
|
+
new(dry_run: dry_run).request(&block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def request_uuid
|
47
|
+
current.request_uuid
|
48
|
+
end
|
33
49
|
|
34
|
-
|
50
|
+
def audits
|
51
|
+
current.audits
|
35
52
|
end
|
36
53
|
end
|
37
54
|
|
38
|
-
|
55
|
+
attr_reader :block, :request_uuid, :dry_run, :locked
|
56
|
+
|
57
|
+
##
|
58
|
+
# Creates a new AuditGroup instance and updates `AuditGroup.current` to it.
|
59
|
+
#
|
60
|
+
# @param request_uuid [String] What all audits within the group will have assigned as their request_uuid.
|
61
|
+
# Useful if you want to group additional operations under a `request_uuid` that already exists in the DB.
|
62
|
+
# @param dry_run [Boolean] If true, the transaction will be rolled back after the block is executed.
|
63
|
+
# @yield operations whose audits should be associated with the same request_uuid.
|
64
|
+
def initialize(request_uuid = SecureRandom.uuid, dry_run: false, &block)
|
39
65
|
@request_uuid = request_uuid
|
66
|
+
@dry_run = dry_run
|
67
|
+
@locked = false
|
68
|
+
|
40
69
|
self.class.current = self
|
70
|
+
|
71
|
+
request(&block) if block_given?
|
41
72
|
end
|
42
73
|
|
74
|
+
##
|
75
|
+
# Sets the `request_uuid` used by the `audited` store, runs the passed in block, then clears the `request_uuid`.
|
76
|
+
# Subsequent `request` calls will also be given the same `request_uuid`.
|
77
|
+
#
|
78
|
+
# @yield operations whose audits should be associated with the same request_uuid.
|
79
|
+
# @return [AuditGroup] itself
|
43
80
|
def request(&block)
|
81
|
+
raise ArgumentError, 'No block given' unless block_given?
|
82
|
+
raise LockError if locked?
|
83
|
+
|
44
84
|
set_request_uuid
|
45
85
|
|
46
|
-
|
86
|
+
if dry_run?
|
87
|
+
ActiveRecord::Base.transaction do
|
88
|
+
block.call
|
89
|
+
|
90
|
+
# Calls .to_a to keep records in memory after rollback
|
91
|
+
@audits = audits.to_a
|
92
|
+
|
93
|
+
raise ActiveRecord::Rollback
|
94
|
+
end
|
95
|
+
else
|
96
|
+
block.call
|
97
|
+
end
|
98
|
+
|
99
|
+
lock!
|
47
100
|
|
48
101
|
self
|
49
102
|
ensure
|
50
103
|
unset_request_uuid
|
51
104
|
end
|
52
105
|
|
53
|
-
|
54
|
-
|
106
|
+
##
|
107
|
+
# @return [Boolean] whether this request is a dry run and will therefore not persist changes.
|
108
|
+
def dry_run?
|
109
|
+
dry_run
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# @return [Boolean] whether this request has already been run and is therefore locked.
|
114
|
+
def locked?
|
115
|
+
locked
|
55
116
|
end
|
56
117
|
|
118
|
+
def lock!
|
119
|
+
@locked = true
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Returns all associated audits. If `dry_run` is true, these will not be persistent in DB.
|
124
|
+
#
|
125
|
+
# @return [ActiveRecord::Relation] all audits associated with the request.
|
57
126
|
def audits
|
58
127
|
Audited::Audit.where(request_uuid: request_uuid)
|
59
128
|
end
|
129
|
+
|
130
|
+
def set_request_uuid
|
131
|
+
self.class.set_request_uuid(request_uuid)
|
132
|
+
end
|
133
|
+
|
134
|
+
def unset_request_uuid
|
135
|
+
self.class.unset_request_uuid
|
136
|
+
end
|
137
|
+
|
138
|
+
def current
|
139
|
+
self.class.current
|
140
|
+
end
|
60
141
|
end
|
metadata
CHANGED
@@ -1,35 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omg-audit-group
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Greenfield
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activerecord
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.2'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7.2'
|
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: '
|
29
|
+
version: '5.2'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7.2'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: audited
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,19 +58,12 @@ executables: []
|
|
58
58
|
extensions: []
|
59
59
|
extra_rdoc_files: []
|
60
60
|
files:
|
61
|
-
- ".gitignore"
|
62
|
-
- ".rspec"
|
63
|
-
- README.md
|
64
|
-
- Rakefile
|
65
|
-
- audit_group.gemspec
|
66
61
|
- lib/audit_group.rb
|
67
|
-
|
68
|
-
- spec/spec_helper.rb
|
69
|
-
homepage: https://github.com/omgreenfield/omg-util/tree/main/audit_group
|
62
|
+
homepage: https://github.com/omgreenfield/audit-group
|
70
63
|
licenses:
|
71
64
|
- MIT
|
72
65
|
metadata:
|
73
|
-
homepage_uri: https://github.com/omgreenfield/
|
66
|
+
homepage_uri: https://github.com/omgreenfield/audit-group
|
74
67
|
rubygems_mfa_required: 'true'
|
75
68
|
post_install_message:
|
76
69
|
rdoc_options: []
|
@@ -80,14 +73,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
73
|
requirements:
|
81
74
|
- - ">="
|
82
75
|
- !ruby/object:Gem::Version
|
83
|
-
version: 2.
|
76
|
+
version: 2.3.0
|
84
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
78
|
requirements:
|
86
79
|
- - ">="
|
87
80
|
- !ruby/object:Gem::Version
|
88
81
|
version: '0'
|
89
82
|
requirements: []
|
90
|
-
rubygems_version: 3.5.
|
83
|
+
rubygems_version: 3.5.17
|
91
84
|
signing_key:
|
92
85
|
specification_version: 4
|
93
86
|
summary: Groups transactions from the `audited` gem into a single request_uuid
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/README.md
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
# AuditGroup
|
2
|
-
|
3
|
-
Group ActiveRecord operations together by assigning all of their audits the same `request_uuid`.
|
4
|
-
|
5
|
-
## TODO
|
6
|
-
|
7
|
-
- [ ] Add `rails` as dependency instead of `active_support`
|
8
|
-
- [ ] Add `dry_run` method
|
9
|
-
|
10
|
-
## Requirements
|
11
|
-
|
12
|
-
- [Audited](https://github.com/collectiveidea/audited) gem
|
13
|
-
|
14
|
-
## Installation
|
15
|
-
|
16
|
-
### From RubyGems.org
|
17
|
-
|
18
|
-
#### Globally
|
19
|
-
|
20
|
-
```sh
|
21
|
-
gem i omg-audit-group
|
22
|
-
```
|
23
|
-
|
24
|
-
#### In `Gemfile`
|
25
|
-
|
26
|
-
```ruby
|
27
|
-
gem 'omg-audit-group'
|
28
|
-
```
|
29
|
-
|
30
|
-
### Testing locally
|
31
|
-
```sh
|
32
|
-
# Build gem
|
33
|
-
rake build
|
34
|
-
|
35
|
-
# Install gem
|
36
|
-
## From this directory
|
37
|
-
rake install
|
38
|
-
|
39
|
-
## From other directory
|
40
|
-
gem i -l /path/to/this/folder/omg-audit-group-0.1.0.gem
|
41
|
-
```
|
42
|
-
|
43
|
-
## Usage
|
44
|
-
|
45
|
-
For convenience, the following operations are delegated from the `AuditGroup` module to the `AuditGroup::Request` class:
|
46
|
-
|
47
|
-
- `new`
|
48
|
-
- `request`
|
49
|
-
- `current`
|
50
|
-
- `request_uuid`
|
51
|
-
- `audits`
|
52
|
-
|
53
|
-
### Using class methods
|
54
|
-
|
55
|
-
```ruby
|
56
|
-
# Group operations under the same request_uuid
|
57
|
-
AuditGroup.request { perform_some_operations }
|
58
|
-
|
59
|
-
# View the last request_uuid
|
60
|
-
AuditGroup.request_uuid
|
61
|
-
|
62
|
-
# View the audits from the last request
|
63
|
-
AuditGroup.audits
|
64
|
-
```
|
65
|
-
|
66
|
-
### Saving Request object for later use
|
67
|
-
|
68
|
-
```ruby
|
69
|
-
# Group operations under the same request_uuid
|
70
|
-
request = AuditGroup.request { perform_some_operations }
|
71
|
-
|
72
|
-
# View the last request_uuid
|
73
|
-
request.request_uuid
|
74
|
-
|
75
|
-
# View the audits from the last request
|
76
|
-
request.audits
|
77
|
-
```
|
78
|
-
|
79
|
-
### Instantiating a group
|
80
|
-
|
81
|
-
You can also create separate `AuditGroup::Request` objects to reuse.
|
82
|
-
|
83
|
-
```ruby
|
84
|
-
group = AuditGroup.new
|
85
|
-
group.request { perform_some_operations }
|
86
|
-
...
|
87
|
-
group.request { perform_more_operations }
|
88
|
-
group.audits
|
89
|
-
```
|
90
|
-
|
91
|
-
## Running tests
|
92
|
-
|
93
|
-
```ruby
|
94
|
-
rspec
|
95
|
-
|
96
|
-
# or
|
97
|
-
bundle exec rspec
|
98
|
-
```
|
data/Rakefile
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
require_relative 'lib/audit_group'
|
2
|
-
|
3
|
-
require 'rake'
|
4
|
-
|
5
|
-
task :spec do
|
6
|
-
sh 'bundle exec rspec'
|
7
|
-
end
|
8
|
-
|
9
|
-
task :build do
|
10
|
-
sh 'gem build audit_group.gemspec'
|
11
|
-
end
|
12
|
-
|
13
|
-
task :push do
|
14
|
-
sh "gem push omg-audit-group-#{AuditGroup::VERSION}.gem"
|
15
|
-
end
|
16
|
-
|
17
|
-
task :publish => :push
|
data/audit_group.gemspec
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'lib/audit_group'
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = 'omg-audit-group'
|
7
|
-
spec.version = AuditGroup::VERSION
|
8
|
-
spec.authors = ['Matthew Greenfield']
|
9
|
-
spec.email = ['mattgreenfield1@gmail.com']
|
10
|
-
|
11
|
-
spec.summary = 'Groups transactions from the `audited` gem into a single request_uuid'
|
12
|
-
spec.description = 'Create, update, and delete records within a block, assign ' \
|
13
|
-
'the same request_uuid to them, and be able to easily view ' \
|
14
|
-
'and undo them'
|
15
|
-
|
16
|
-
spec.homepage = 'https://github.com/omgreenfield/omg-util/tree/main/audit_group'
|
17
|
-
spec.license = 'MIT'
|
18
|
-
spec.required_ruby_version = '>= 2.7.0'
|
19
|
-
|
20
|
-
spec.metadata['homepage_uri'] = spec.homepage
|
21
|
-
spec.metadata['rubygems_mfa_required'] = 'true'
|
22
|
-
|
23
|
-
spec.files = Dir.chdir(__dir__) do
|
24
|
-
`git ls-files -z`.split("\x0").reject do |f|
|
25
|
-
(File.expand_path(f) == __FILE__) ||
|
26
|
-
f.start_with?(*%w[spec/.git .github Gemfile])
|
27
|
-
end
|
28
|
-
end
|
29
|
-
spec.require_paths = ['lib']
|
30
|
-
|
31
|
-
spec.add_dependency 'activesupport', '>= 6.0', '< 8.0'
|
32
|
-
spec.add_dependency 'audited', '>= 4.9', '< 6.0'
|
33
|
-
end
|
data/spec/audit_group_spec.rb
DELETED
@@ -1,108 +0,0 @@
|
|
1
|
-
RSpec.describe AuditGroup do
|
2
|
-
describe 'class methods' do
|
3
|
-
describe '.current' do
|
4
|
-
it 'returns the last request created' do
|
5
|
-
request = described_class.request {}
|
6
|
-
expect(described_class.current).to eq(request)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
describe '.set_request_uuid' do
|
11
|
-
it "sets the Audit store's current_request_uuid" do
|
12
|
-
described_class.set_request_uuid('123')
|
13
|
-
expect(Audited.store[:current_request_uuid]).to eq('123')
|
14
|
-
|
15
|
-
described_class.set_request_uuid
|
16
|
-
expect(Audited.store[:current_request_uuid]).to match(/\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe '.unset_request_uuid' do
|
21
|
-
it "resets the Audit store's current_request_uuid" do
|
22
|
-
Audited.store[:current_request_uuid] = '123'
|
23
|
-
described_class.unset_request_uuid
|
24
|
-
expect(Audited.store[:current_request_uuid]).to be_nil
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe '.reset' do
|
29
|
-
it 'unsets the request_uuid and current request' do
|
30
|
-
described_class.set_request_uuid('123')
|
31
|
-
described_class.current = 'some request'
|
32
|
-
|
33
|
-
expect(Audited.store[:current_request_uuid]).to eq('123')
|
34
|
-
expect(described_class.current).to eq('some request')
|
35
|
-
|
36
|
-
described_class.reset
|
37
|
-
|
38
|
-
expect(Audited.store[:current_request_uuid]).to be_nil
|
39
|
-
expect(described_class.current).to be_nil
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe '.request' do
|
44
|
-
it 'raises an ArgumentError if no block is given and no active group' do
|
45
|
-
expect { described_class.request }.to raise_error(ArgumentError, 'No block given and no active group')
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'creates a new request if block is given' do
|
49
|
-
expect { |block| described_class.request(&block) }.to yield_control
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe '.request_uuid' do
|
54
|
-
it 'delegates to current' do
|
55
|
-
described_class.request {}
|
56
|
-
expect(described_class.request_uuid).to eq(described_class.current.request_uuid)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
describe '.audits' do
|
61
|
-
it 'delegates to current' do
|
62
|
-
described_class.new('123')
|
63
|
-
audited_audit = class_double('Audited::Audit').as_stubbed_const
|
64
|
-
expect(audited_audit).to receive(:where).with(request_uuid: '123').and_return('some audits')
|
65
|
-
expect(described_class.audits).to eq('some audits')
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe 'instance methods' do
|
71
|
-
describe '#initialize' do
|
72
|
-
it 'sets the request_uuid and current request' do
|
73
|
-
request = described_class.new('123')
|
74
|
-
expect(request.request_uuid).to eq('123')
|
75
|
-
expect(described_class.current).to eq(request)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe '#request' do
|
80
|
-
it 'sets the current_request_uuid, calls the block, then resets current_request_uuid' do
|
81
|
-
request = described_class.new('123')
|
82
|
-
|
83
|
-
request.request do
|
84
|
-
expect(Audited.store[:current_request_uuid]).to eq('123')
|
85
|
-
end
|
86
|
-
|
87
|
-
expect(Audited.store[:current_request_uuid]).to be_nil
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
describe '#set_request_uuid' do
|
92
|
-
it 'delegates to class' do
|
93
|
-
request = described_class.new('123')
|
94
|
-
expect(request).to receive(:set_request_uuid)
|
95
|
-
request.set_request_uuid
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
describe '#audits' do
|
100
|
-
it 'returns audits with request_uuid' do
|
101
|
-
request = described_class.new('123')
|
102
|
-
audited_audit = class_double('Audited::Audit').as_stubbed_const
|
103
|
-
expect(audited_audit).to receive(:where).with(request_uuid: '123').and_return('some audits')
|
104
|
-
expect(request.audits).to eq('some audits')
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'audit_group'
|
4
|
-
|
5
|
-
RSpec.configure do |config|
|
6
|
-
# Enable flags like --only-failures and --next-failure
|
7
|
-
config.example_status_persistence_file_path = '.rspec_status'
|
8
|
-
|
9
|
-
# Disable RSpec exposing methods globally on `Module` and `main`
|
10
|
-
config.disable_monkey_patching!
|
11
|
-
|
12
|
-
config.expect_with :rspec do |c|
|
13
|
-
c.syntax = :expect
|
14
|
-
end
|
15
|
-
end
|