omg-audit-group 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ sandbox.md
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
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
+ ```
@@ -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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AuditGroup
4
+ VERSION = "0.1.0"
5
+ end
@@ -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
@@ -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: []