omg-audit-group 0.1.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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/README.md +60 -0
- data/audit_group.gemspec +38 -0
- data/lib/audit_group/request.rb +59 -0
- data/lib/audit_group/version.rb +5 -0
- data/lib/audit_group.rb +13 -0
- data/spec/audit_group/request_spec.rb +110 -0
- data/spec/audit_group_spec.rb +44 -0
- data/spec/spec_helper.rb +15 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4aefcd1c0eb006272723f7ed68f14cd719e6480d833e9354730ee42340d6b814
|
4
|
+
data.tar.gz: 418949a9ea417499e1ff0566f1255940c273bcc5404311bfd4352eecc34b3196
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1ef815f6b87adb3fe2df279b84dd94a7ff48f8075fa2e91292680b270bec764ff1800b38b90523d02c7f5ed92d936fcdc95bf56548a454f4e899ad9e47672f29
|
7
|
+
data.tar.gz: 7ce8a2a142907e59690af0cf912302aed6fe607cefd1b133b43520517a68dd1049845d6ef32155c73c088eaebe7ab4011899e3ed859ec48c8934567f788b2299
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# AuditGroup
|
2
|
+
|
3
|
+
Group ActiveRecord operations together by assigning all of their audits the same `request_uuid`.
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
- [Audited](https://github.com/collectiveidea/audited) gem
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
### Testing locally
|
12
|
+
```sh
|
13
|
+
# Build gem
|
14
|
+
gem build audit_group.gemspec
|
15
|
+
|
16
|
+
# Install gem
|
17
|
+
gem i -l /path/to/this/repo/omg-audit_group-0.1.0.gem
|
18
|
+
```
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
For convenience, the following operations are delegated from the `AuditGroup` module to the `AuditGroup::Request` class:
|
23
|
+
|
24
|
+
- `new`
|
25
|
+
- `request`
|
26
|
+
- `current`
|
27
|
+
- `request_uuid`
|
28
|
+
- `audits`
|
29
|
+
|
30
|
+
Here are some use cases:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
# Group operations under the same request_uuid
|
34
|
+
AuditGroup.request { perform_some_operations }
|
35
|
+
|
36
|
+
# View the last request_uuid (the above also returns it)
|
37
|
+
AuditGroup.request_uuid
|
38
|
+
|
39
|
+
# View the audits from the last request
|
40
|
+
AuditGroup.audits
|
41
|
+
```
|
42
|
+
|
43
|
+
You can also create separate `AuditGroup::Request` objects to reuse.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
group = AuditGroup.new
|
47
|
+
group.request { perform_some_operations }
|
48
|
+
...
|
49
|
+
group.request { perform_more_operations }
|
50
|
+
group.audits
|
51
|
+
```
|
52
|
+
|
53
|
+
## Running tests
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
rspec
|
57
|
+
|
58
|
+
# or
|
59
|
+
bundle exec rspec
|
60
|
+
```
|
data/audit_group.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/audit_group/version'
|
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
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(__dir__) do
|
26
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
(File.expand_path(f) == __FILE__) ||
|
28
|
+
f.start_with?(*%w[spec/.git .github Gemfile])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
spec.require_paths = ['lib']
|
32
|
+
|
33
|
+
spec.add_dependency 'activesupport', '>= 6.0', '< 8.0'
|
34
|
+
spec.add_dependency 'audited', '>= 4.9', '< 6.0'
|
35
|
+
|
36
|
+
# For more information and examples about making a new gem, check out our
|
37
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
38
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require 'audited'
|
3
|
+
require 'pry-byebug'
|
4
|
+
|
5
|
+
module AuditGroup
|
6
|
+
class Request
|
7
|
+
attr_reader :block, :request_uuid
|
8
|
+
|
9
|
+
delegate :current, :unset_request_uuid, to: :class
|
10
|
+
|
11
|
+
class << self
|
12
|
+
delegate :request_uuid, :audits, to: :current
|
13
|
+
|
14
|
+
attr_accessor :current
|
15
|
+
|
16
|
+
def set_request_uuid(request_uuid = SecureRandom.uuid)
|
17
|
+
Audited.store[:current_request_uuid] = request_uuid
|
18
|
+
end
|
19
|
+
|
20
|
+
def unset_request_uuid
|
21
|
+
Audited.store.delete(:current_request_uuid)
|
22
|
+
end
|
23
|
+
|
24
|
+
def reset
|
25
|
+
unset_request_uuid
|
26
|
+
@current = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def request(&block)
|
30
|
+
raise ArgumentError, 'No block given and no active group' unless block_given?
|
31
|
+
|
32
|
+
new.request(&block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize(request_uuid = SecureRandom.uuid)
|
37
|
+
@request_uuid = request_uuid
|
38
|
+
self.class.current = self
|
39
|
+
end
|
40
|
+
|
41
|
+
def request(&block)
|
42
|
+
set_request_uuid
|
43
|
+
|
44
|
+
block.call if block.present?
|
45
|
+
|
46
|
+
self
|
47
|
+
ensure
|
48
|
+
unset_request_uuid
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_request_uuid
|
52
|
+
self.class.set_request_uuid(request_uuid)
|
53
|
+
end
|
54
|
+
|
55
|
+
def audits
|
56
|
+
Audited::Audit.where(request_uuid: request_uuid)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/audit_group.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'audit_group/request'
|
4
|
+
require_relative 'audit_group/version'
|
5
|
+
|
6
|
+
require 'active_support/all'
|
7
|
+
require 'audited'
|
8
|
+
|
9
|
+
module AuditGroup
|
10
|
+
class << self
|
11
|
+
delegate :new, :request, :current, :request_uuid, :audits, to: Request
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'audit_group/request'
|
2
|
+
|
3
|
+
RSpec.describe AuditGroup::Request do
|
4
|
+
describe 'class methods' do
|
5
|
+
describe '.current' do
|
6
|
+
it 'returns the last request created' do
|
7
|
+
request = described_class.request {}
|
8
|
+
expect(described_class.current).to eq(request)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.set_request_uuid' do
|
13
|
+
it "sets the Audit store's current_request_uuid" do
|
14
|
+
described_class.set_request_uuid('123')
|
15
|
+
expect(Audited.store[:current_request_uuid]).to eq('123')
|
16
|
+
|
17
|
+
described_class.set_request_uuid
|
18
|
+
expect(Audited.store[:current_request_uuid]).to match(/\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.unset_request_uuid' do
|
23
|
+
it "resets the Audit store's current_request_uuid" do
|
24
|
+
Audited.store[:current_request_uuid] = '123'
|
25
|
+
described_class.unset_request_uuid
|
26
|
+
expect(Audited.store[:current_request_uuid]).to be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.reset' do
|
31
|
+
it 'unsets the request_uuid and current request' do
|
32
|
+
described_class.set_request_uuid('123')
|
33
|
+
described_class.current = 'some request'
|
34
|
+
|
35
|
+
expect(Audited.store[:current_request_uuid]).to eq('123')
|
36
|
+
expect(described_class.current).to eq('some request')
|
37
|
+
|
38
|
+
described_class.reset
|
39
|
+
|
40
|
+
expect(Audited.store[:current_request_uuid]).to be_nil
|
41
|
+
expect(described_class.current).to be_nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '.request' do
|
46
|
+
it 'raises an ArgumentError if no block is given and no active group' do
|
47
|
+
expect { described_class.request }.to raise_error(ArgumentError, 'No block given and no active group')
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'creates a new request if block is given' do
|
51
|
+
expect { |block| described_class.request(&block) }.to yield_control
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '.request_uuid' do
|
56
|
+
it 'delegates to current' do
|
57
|
+
described_class.request {}
|
58
|
+
expect(described_class.request_uuid).to eq(described_class.current.request_uuid)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '.audits' do
|
63
|
+
it 'delegates to current' do
|
64
|
+
described_class.new('123')
|
65
|
+
audited_audit = class_double('Audited::Audit').as_stubbed_const
|
66
|
+
expect(audited_audit).to receive(:where).with(request_uuid: '123').and_return('some audits')
|
67
|
+
expect(described_class.audits).to eq('some audits')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'instance methods' do
|
73
|
+
describe '#initialize' do
|
74
|
+
it 'sets the request_uuid and current request' do
|
75
|
+
request = described_class.new('123')
|
76
|
+
expect(request.request_uuid).to eq('123')
|
77
|
+
expect(described_class.current).to eq(request)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe '#request' do
|
82
|
+
it 'sets the current_request_uuid, calls the block, then resets current_request_uuid' do
|
83
|
+
request = described_class.new('123')
|
84
|
+
|
85
|
+
request.request do
|
86
|
+
expect(Audited.store[:current_request_uuid]).to eq('123')
|
87
|
+
end
|
88
|
+
|
89
|
+
expect(Audited.store[:current_request_uuid]).to be_nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe '#set_request_uuid' do
|
94
|
+
it 'delegates to class' do
|
95
|
+
request = described_class.new('123')
|
96
|
+
expect(request).to receive(:set_request_uuid)
|
97
|
+
request.set_request_uuid
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '#audits' do
|
102
|
+
it 'returns audits with request_uuid' do
|
103
|
+
request = described_class.new('123')
|
104
|
+
audited_audit = class_double('Audited::Audit').as_stubbed_const
|
105
|
+
expect(audited_audit).to receive(:where).with(request_uuid: '123').and_return('some audits')
|
106
|
+
expect(request.audits).to eq('some audits')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe AuditGroup do
|
4
|
+
it 'has a version number' do
|
5
|
+
expect(AuditGroup::VERSION).not_to be_nil
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.new' do
|
9
|
+
it 'delegates to Request' do
|
10
|
+
expect(AuditGroup.new).to be_a(AuditGroup::Request)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '.request' do
|
15
|
+
it 'creates a new Request' do
|
16
|
+
request = AuditGroup.request { puts 'Hi, Mom!' }
|
17
|
+
|
18
|
+
expect(request).to be_a(AuditGroup::Request)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.current' do
|
23
|
+
it 'returns the last created Request object' do
|
24
|
+
request = AuditGroup.request { puts 'Hi, Dad!' }
|
25
|
+
expect(AuditGroup.current).to eq(request)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '.request_uuid' do
|
30
|
+
it 'returns the current request_uuid' do
|
31
|
+
request = AuditGroup.request { puts 'Hi, Steve!' }
|
32
|
+
expect(AuditGroup.request_uuid).to eq(request.request_uuid)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '.audits' do
|
37
|
+
it 'delegates to Request' do
|
38
|
+
AuditGroup.request { puts "Who's Steve?" }
|
39
|
+
audited_audit = class_double('Audited::Audit').as_stubbed_const
|
40
|
+
expect(audited_audit).to receive(:where).with(request_uuid: an_instance_of(String)).and_return('some audits')
|
41
|
+
expect(AuditGroup.audits).to eq('some audits')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
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
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: omg-audit-group
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew Greenfield
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-04-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '8.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '6.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '8.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: audited
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '4.9'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '6.0'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '4.9'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '6.0'
|
53
|
+
description: Create, update, and delete records within a block, assign the same request_uuid
|
54
|
+
to them, and be able to easily view and undo them
|
55
|
+
email:
|
56
|
+
- mattgreenfield1@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- ".gitignore"
|
62
|
+
- ".rspec"
|
63
|
+
- README.md
|
64
|
+
- audit_group.gemspec
|
65
|
+
- lib/audit_group.rb
|
66
|
+
- lib/audit_group/request.rb
|
67
|
+
- lib/audit_group/version.rb
|
68
|
+
- spec/audit_group/request_spec.rb
|
69
|
+
- spec/audit_group_spec.rb
|
70
|
+
- spec/spec_helper.rb
|
71
|
+
homepage: https://github.com/omgreenfield/omg-util/tree/main/audit_group
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata:
|
75
|
+
homepage_uri: https://github.com/omgreenfield/omg-util/tree/main/audit_group
|
76
|
+
rubygems_mfa_required: 'true'
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.7.0
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubygems_version: 3.5.9
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Groups transactions from the `audited` gem into a single request_uuid
|
96
|
+
test_files: []
|