whodunit 0.3.1 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63c3f8d658cdf1f7b9e7ee954ba759ccddb2d70171f1e755ecbcd2146e314143
4
- data.tar.gz: 33e6c62249309d051b20197d5a4a20df8a51fd9472a05aaf9243f88a2a092a4c
3
+ metadata.gz: b118c7a04ca24e4cfd6aa759e57b5c92e51be74f87b35a89ae6e5654f3a56051
4
+ data.tar.gz: db5c8c236bd170f7ce42b14682c3c44c6eaaae2dc125b6c8e9cdf9ef7a9a9596
5
5
  SHA512:
6
- metadata.gz: b34b74b871fa5a07491bf0a2516131024d3f6b464bc387815ec61b423c3ab32384b394581ca21b1a6d69508b8aa1c3d9b71f77878681ce4f6604b844d86ea2e8
7
- data.tar.gz: 3b790f6f5edb918b609689de6dceee29699ae19d85e214019b6bfc55e7c4ab820907e67e631d7fb68b4bb11289a66d62e5a81857e78c3007428bd81b4e1d938d
6
+ metadata.gz: 4324dc93c29055aaa6dcc02b1999484d8108a4212eb8474185d5c0dee47e6d99fc88ed938d344f17bf75747a2eb5023ef2d6295d5308d9c838fd9b2f00c349dd
7
+ data.tar.gz: 6f31152d504e0b80a81992c3f62f190ac9de4aba73d0a964e24c116052ea5093629b6182eff58d6c9f811c2b3bec95b5385f49ef45429cc8f11d66a6d190d988
data/.rubocop.yml CHANGED
@@ -6,7 +6,7 @@ plugins:
6
6
 
7
7
  AllCops:
8
8
  NewCops: enable
9
- TargetRubyVersion: 3.1
9
+ TargetRubyVersion: 3.2
10
10
  Exclude:
11
11
  - 'vendor/**/*'
12
12
  - 'tmp/**/*'
@@ -114,12 +114,12 @@ Metrics/AbcSize:
114
114
  - 'spec/**/*'
115
115
 
116
116
  Metrics/CyclomaticComplexity:
117
- Max: 8
117
+ Max: 10
118
118
  Exclude:
119
119
  - 'spec/**/*'
120
120
 
121
121
  Metrics/PerceivedComplexity:
122
- Max: 8
122
+ Max: 10
123
123
  Exclude:
124
124
  - 'spec/**/*'
125
125
  Gemspec/DevelopmentDependencies:
data/CHANGELOG.md CHANGED
@@ -5,7 +5,45 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.4.0] - 2025-05-20
9
+
10
+ ### Breaking Changes
11
+
12
+ - Dropped support for Ruby 3.1. Minimum supported Ruby version is now **3.2**.
13
+
14
+ ### Fixed
15
+
16
+ - `TableDefinitionExtension`: replaced `included { attr_accessor :_whodunit_stamps_added }` with
17
+ explicit reader/writer methods so the accessor is defined correctly when the module is **prepended**
18
+ (as the Railtie does) rather than included. Previously the accessor was silently missing in
19
+ production, causing `@_whodunit_stamps_added` to be inaccessible via the public API.
20
+
21
+ ### Changed
22
+
23
+ - **Test suite**: eliminated all hand-rolled ActiveRecord and Railtie mocks in favour of genuine
24
+ infrastructure — real `ActiveRecord::Base` subclasses backed by an in-memory SQLite3 database,
25
+ and real `ActiveRecord::ConnectionAdapters::TableDefinition` instances for migration-helper tests.
26
+ Callbacks, dirty tracking, `belongs_to` reflections, and `column_names` now go through actual AR
27
+ code paths rather than no-op stubs.
28
+ - `spec/support/rails_mocks.rb` — emptied; `activesupport` is a runtime dependency and needs no
29
+ re-implementation in tests.
30
+ - `spec/support/test_models.rb` — replaced `MockActiveRecord` stub class with real AR models
31
+ (`WhodunitRecord`, `WhodunitSoftDeleteRecord`) on an in-memory SQLite3 schema; backward-compat
32
+ aliases preserved.
33
+ - `spec/spec_helper.rb` — added `rescue Bundler::GemNotFound` guard on `require "bundler/setup"`
34
+ to allow running specs directly without `bundle exec`; wrapped every example in an AR transaction
35
+ that rolls back on completion; added missing config keys to `ORIGINAL_WHODUNIT_CONFIG`.
36
+ - `spec/whodunit/table_definition_extension_spec.rb` — now tests the real
37
+ `ActiveRecord::ConnectionAdapters::TableDefinition` with `TableDefinitionExtension` prepended,
38
+ rather than an anonymous class that reimplemented the extension logic internally.
39
+ - `spec/whodunit/stampable_spec.rb` — `being_soft_deleted?` tests use real AR dirty tracking via
40
+ genuine attribute writes; callback-integration tests persist records and assert database values
41
+ after `reload`.
42
+ - `spec/whodunit/migration_helpers_spec.rb` — `whodunit_stamps(table_def)` path uses a real
43
+ `TableDefinitionExtension`-prepended `TableDefinition` instance instead of a double.
44
+ - `spec/whodunit/per_model_config_spec.rb`, `railtie_spec.rb`,
45
+ `reverse_associations_integration_spec.rb` — all converted to real AR anonymous subclasses;
46
+ removed stubs for `before_create`, `belongs_to`, and `column_names`.
9
47
 
10
48
  ## [0.3.0] - 2025-01-24
11
49
 
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/whodunit.svg)](https://badge.fury.io/rb/whodunit)
4
4
  [![CI](https://github.com/kanutocd/whodunit/workflows/CI/badge.svg)](https://github.com/kanutocd/whodunit/actions)
5
5
  [![Coverage Status](https://codecov.io/gh/kanutocd/whodunit/branch/main/graph/badge.svg)](https://codecov.io/gh/kanutocd/whodunit)
6
- [![Ruby Version](https://img.shields.io/badge/ruby-%3E%3D%203.1.0-ruby.svg)](https://www.ruby-lang.org/en/)
6
+ [![Ruby Version](https://img.shields.io/badge/ruby-%3E%3D%203.2-ruby.svg)](https://www.ruby-lang.org/en/)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
8
 
9
9
  Lightweight creator/updater/deleter tracking for Rails ActiveRecord models.
@@ -16,7 +16,7 @@ Whodunit provides simple auditing for Rails applications by tracking who created
16
16
 
17
17
  ## Requirements
18
18
 
19
- - Ruby 3.1.1+ (tested on 3.1.1, 3.2.0, 3.3.0, 3.4, 4.0). See the [the ruby-version matrix strategy of the CI workflow](https://github.com/kanutocd/whodunit/blob/main/.github/workflows/ci.yml#L15).
19
+ - Ruby 3.2+ (tested on 3.2, 3.3, 3.4, 4.0). See the [the ruby-version matrix strategy of the CI workflow](https://github.com/kanutocd/whodunit/blob/main/.github/workflows/ci.yml#L15).
20
20
  - Rails 7.2+ (tested on 7.2, 8.2, and edge)
21
21
  - ActiveRecord for database operations
22
22
 
@@ -22,19 +22,19 @@ module Whodunit
22
22
 
23
23
  # Extend ActiveRecord with migration helpers.
24
24
  #
25
- # This initializer adds the MigrationHelpers module to ActiveRecord,
25
+ # This initializer adds the MigrationHelpers module to ActiveRecord::Migration,
26
26
  # making methods like add_whodunit_stamps available in migrations.
27
27
  # It also extends TableDefinition for automatic whodunit_stamps injection.
28
28
  #
29
29
  # @api private
30
30
  initializer "whodunit.extend_active_record" do |_app|
31
31
  ActiveSupport.on_load(:active_record) do
32
- extend Whodunit::MigrationHelpers
32
+ ActiveRecord::Migration.include(Whodunit::MigrationHelpers)
33
33
 
34
- # Extend TableDefinition for automatic whodunit_stamps injection
35
- ActiveRecord::ConnectionAdapters::TableDefinition.include(
36
- Whodunit::TableDefinitionExtension
37
- )
34
+ # We use ActiveRecord::ConnectionAdapters::TableDefinition#timestamps to automatically inject whodunit_stamps
35
+ ActiveRecord::ConnectionAdapters::TableDefinition.prepend(Whodunit::TableDefinitionExtension)
36
+ # Reuse the `whodunit_stamps` flow in Whodunit::MigrationHelpers module
37
+ ActiveRecord::ConnectionAdapters::TableDefinition.extend(Whodunit::MigrationHelpers)
38
38
  end
39
39
  end
40
40
 
@@ -145,6 +145,8 @@ module Whodunit
145
145
  private
146
146
 
147
147
  def setup_whodunit_associations
148
+ return if abstract_class?
149
+
148
150
  setup_creator_association if creator_column_exists? && model_creator_enabled?
149
151
  setup_updater_association if updater_column_exists? && model_updater_enabled?
150
152
  setup_deleter_association if deleter_column_exists? && model_deleter_enabled? && soft_delete_enabled?
@@ -28,30 +28,33 @@ module Whodunit
28
28
  module TableDefinitionExtension
29
29
  extend ActiveSupport::Concern
30
30
 
31
- included do
32
- # Track whether whodunit_stamps have been automatically added
33
- attr_accessor :_whodunit_stamps_added
31
+ def _whodunit_stamps_added
32
+ @_whodunit_stamps_added
33
+ end
34
+
35
+ def _whodunit_stamps_added=(value)
36
+ @_whodunit_stamps_added = value
34
37
  end
35
38
 
36
39
  # Override timestamps to trigger automatic whodunit_stamps injection
37
40
  def timestamps(**options)
41
+ options = options.dup
42
+ skip = options.delete(:skip_whodunit_stamps)
38
43
  result = super
39
44
 
40
- # Auto-inject whodunit_stamps after timestamps if enabled and not already added
41
- if Whodunit.auto_inject_whodunit_stamps &&
42
- !@_whodunit_stamps_added &&
43
- !options[:skip_whodunit_stamps]
45
+ if Whodunit.auto_inject_whodunit_stamps && !_whodunit_stamps_added && !skip
44
46
  whodunit_stamps(include_deleter: :auto)
45
- @_whodunit_stamps_added = true
46
47
  end
47
48
 
48
49
  result
49
50
  end
50
51
 
51
- # Also override whodunit_stamps to track that they've been added
52
- def whodunit_stamps(**options)
53
- @_whodunit_stamps_added = true
54
- super
52
+ # assign true tp the tracker `@_whodunit_stamps_added` before the
53
+ # reuse/call of the `whodunit_stamps` flow from the Whodunit::MigrationHelpers module (see railtie.rb)
54
+ #
55
+ def whodunit_stamps(include_deleter: :auto, creator_type: nil, updater_type: nil, deleter_type: nil)
56
+ self._whodunit_stamps_added = true
57
+ self.class.whodunit_stamps(self, include_deleter:, creator_type:, updater_type:, deleter_type:)
55
58
  end
56
59
  end
57
60
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Whodunit
4
- VERSION = "0.3.1"
4
+ VERSION = "0.4.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whodunit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken C. Demanawa
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-05-13 00:00:00.000000000 Z
11
+ date: 2026-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
194
  version: '3.0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: sqlite3
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '2.9'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '2.9'
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: yard
197
211
  requirement: !ruby/object:Gem::Requirement
@@ -259,9 +273,9 @@ require_paths:
259
273
  - lib
260
274
  required_ruby_version: !ruby/object:Gem::Requirement
261
275
  requirements:
262
- - - ">"
276
+ - - ">="
263
277
  - !ruby/object:Gem::Version
264
- version: '3.1'
278
+ version: '3.2'
265
279
  required_rubygems_version: !ruby/object:Gem::Requirement
266
280
  requirements:
267
281
  - - ">="