omg-audit-group 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c0c376f111fedecd658dac64a321545b036c3a672cb8a7b4e8f6c443a90fbe74
4
- data.tar.gz: d8c9fa53d36b22ef3b57c41bf11a73131e6c90ac8e011c45604b155025db7251
3
+ metadata.gz: c2103693c9d639bfce07ecae254b8df32a5571ed8084a141aa3b7d072ea62632
4
+ data.tar.gz: 8b49dfc610cacdf906fa910414064ad4cec032a14809512111e22c3f290c5e38
5
5
  SHA512:
6
- metadata.gz: 50c5f348251c2c296f3f778eb3704992b2c459926c0f4814e8a13cba5906a90349844037316aa682840518ca990312d5317ab2efaef40423fd5c41f27cb5d5fa
7
- data.tar.gz: 9f49b04443555acd365e821367d378b63e832a76e16b8cf86d82a5dcfcca2d4356323330fe67712d40820676c8cda8f935d5d92547a225cc82847486a73bea09
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.2'
6
+ VERSION = '0.1.4'
8
7
 
9
- attr_reader :block, :request_uuid
10
-
11
- delegate :current, :unset_request_uuid, to: :class
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
- delegate :request_uuid, :audits, to: :current
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
- def request(&block)
32
- raise ArgumentError, 'No block given and no active group' unless block_given?
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
- new.request(&block)
50
+ def audits
51
+ current.audits
35
52
  end
36
53
  end
37
54
 
38
- def initialize(request_uuid = SecureRandom.uuid)
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
- block.call if block.present?
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
- def set_request_uuid
54
- self.class.set_request_uuid(request_uuid)
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.2
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-05-08 00:00:00.000000000 Z
11
+ date: 2024-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activesupport
14
+ name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '6.0'
19
+ version: '5.2'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '8.0'
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: '6.0'
29
+ version: '5.2'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '8.0'
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
- - spec/audit_group_spec.rb
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/omg-util/tree/main/audit_group
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.7.0
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.10
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
@@ -1,12 +0,0 @@
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 DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
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
@@ -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