standard_ledger 0.5.0 → 0.5.1

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: 89af058a7d94051bc75f8e853d1be397270b52bc5a02020dfdd41484c6cacda5
4
- data.tar.gz: 50eef558981621f3561c42095d294f87f09d7ed18e8fc5a5919c0801262f257b
3
+ metadata.gz: 74163637dfcb14c019f6481391644b45849cad04108b580e5a8de524720ed1ca
4
+ data.tar.gz: d022e52db16ba6e838c47c9e94ead8fa1f876afb37ffa5f8b3b5390d4877b157
5
5
  SHA512:
6
- metadata.gz: 16d8c529a99909adb4739feb0ea76e996ebd709c044bc56dd2722bc041f4c17670d2bb383a48072df9a686bc02b1c2a49add8206618ddeb7fb86dd2b45e61c9f
7
- data.tar.gz: 5f152b064c69e8da3f7e2767c4b3914da197599ed64ecc8e512be6c34e334af25337f83fd68080c7811a3f4772df647d5799ae635cb0116409286455bd86bf0e
6
+ metadata.gz: e9b7f1b51851431f1e44c5129dac815517ce064860a83d210d8f94ed8b30e7a90dc393d92af4e702516fcc0a804e613cc7859d582b4ce042d31220970835fb5d
7
+ data.tar.gz: c11d063fd3e01c8feb06176742df0167ff363c375de4c03d979a7dee52ca21e1388917fd2e1b10e770409b2a703aa5f223f496bc8f2619368b40fa0c323a1cb9
data/CHANGELOG.md CHANGED
@@ -6,6 +6,26 @@ project adheres to [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.5.1] - 2026-09-24
10
+
11
+ ### Fixed
12
+ - The `post_ledger_entry` RSpec matcher now listens on the channel
13
+ `StandardLedger::EventEmitter` emits through. It only subscribed to
14
+ `ActiveSupport::Notifications`, but on Rails 8.1+ the gem emits through
15
+ `Rails.event.notify`, so the matcher saw no events at all: every positive
16
+ expectation failed and every `not_to post_ledger_entry` passed without
17
+ checking anything. When `EventEmitter.rails_event_available?` is true, the
18
+ matcher now subscribes a collector to `Rails.event` for the block and
19
+ unsubscribes it afterwards.
20
+
21
+ ### Documentation
22
+ - README **Testing** section (and `AGENTS.md`) said the RSpec support hook
23
+ calls `StandardLedger.reset!`. It calls `reset_mode_overrides!`, which keeps
24
+ host initializer configuration intact.
25
+ - The engine initializer comment now tells hosts to subscribe via
26
+ `Rails.event.subscribe` on Rails 8.1+ rather than
27
+ `ActiveSupport::Notifications.subscribe`.
28
+
9
29
  ## [0.5.0] - 2026-09-22
10
30
 
11
31
  ### Changed
@@ -446,7 +466,8 @@ roadmap.
446
466
  and `:trigger` (host-owned, gem records rebuild SQL).
447
467
  - `standard_ledger:doctor` rake task (verifies trigger presence, etc.).
448
468
 
449
- [Unreleased]: https://github.com/rarebit-one/standard_ledger/compare/v0.5.0...HEAD
469
+ [Unreleased]: https://github.com/rarebit-one/standard_ledger/compare/v0.5.1...HEAD
470
+ [0.5.1]: https://github.com/rarebit-one/standard_ledger/compare/v0.5.0...v0.5.1
450
471
  [0.5.0]: https://github.com/rarebit-one/standard_ledger/compare/v0.4.0...v0.5.0
451
472
  [0.4.0]: https://github.com/rarebit-one/standard_ledger/compare/v0.3.0...v0.4.0
452
473
  [0.3.0]: https://github.com/rarebit-one/standard_ledger/compare/v0.2.0...v0.3.0
data/README.md CHANGED
@@ -381,12 +381,15 @@ The gem ships an opt-in RSpec support file. Hosts add this to their
381
381
  require "standard_ledger/rspec"
382
382
  ```
383
383
 
384
- That registers a `before(:each)` hook that calls `StandardLedger.reset!`
385
- between examples (so per-spec configuration doesn't leak), and exposes:
384
+ That registers a `before(:each)` hook that calls
385
+ `StandardLedger.reset_mode_overrides!` between examples (so `with_modes`
386
+ overrides don't leak). It deliberately does not call the full `reset!`, which
387
+ would wipe configuration your initializers set up. It also exposes:
386
388
 
387
389
  - `post_ledger_entry(EntryClass).with(...)` — a block matcher that
388
- subscribes to the `<namespace>.entry.created` notification for the
389
- duration of the block and asserts an entry of the expected class was
390
+ subscribes to the `<namespace>.entry.created` event for the duration of
391
+ the block, on the same channel the gem emits through (`Rails.event` on
392
+ Rails 8.1+, `ActiveSupport::Notifications` otherwise), and asserts an entry of the expected class was
390
393
  written (with optional `kind:`/`targets:`/`attrs:` constraints).
391
394
 
392
395
  ```ruby
@@ -12,8 +12,10 @@ module StandardLedger
12
12
 
13
13
  initializer "standard_ledger.notifications", after: :load_config_initializers do
14
14
  # Notification wiring lands here in a follow-up PR. Today this is a
15
- # no-op — the gem emits events but ships no internal subscribers; hosts
16
- # subscribe directly via ActiveSupport::Notifications.subscribe.
15
+ # no-op — the gem emits events but ships no internal subscribers. On
16
+ # Rails 8.1+ events go through `Rails.event.notify`, so hosts subscribe
17
+ # with `Rails.event.subscribe`; on older Rails they fall back to
18
+ # ActiveSupport::Notifications (see StandardLedger::EventEmitter).
17
19
  end
18
20
 
19
21
  # Engines auto-discover `lib/tasks/*.rake` in most Rails versions, but
@@ -1,5 +1,28 @@
1
1
  require "rspec/expectations"
2
2
  require "active_support/notifications"
3
+ require "standard_ledger/event_emitter"
4
+
5
+ module StandardLedger
6
+ module RSpec
7
+ # Collects `<namespace>.entry.created` payloads from `Rails.event` for the
8
+ # duration of a `post_ledger_entry` block. A dedicated object (not a
9
+ # Proc) because `EventReporter#unsubscribe` matches with `===`.
10
+ #
11
+ # @api private
12
+ class RailsEventCollector
13
+ attr_reader :payloads
14
+
15
+ def initialize(event_name)
16
+ @event_name = event_name
17
+ @payloads = []
18
+ end
19
+
20
+ def emit(event)
21
+ @payloads << event[:payload] if event[:name] == @event_name
22
+ end
23
+ end
24
+ end
25
+ end
3
26
 
4
27
  # `post_ledger_entry` — assert that a block of code wrote a ledger entry.
5
28
  #
@@ -22,7 +45,9 @@ require "active_support/notifications"
22
45
  # expect { ... }.to_not post_ledger_entry(VoucherRecord)
23
46
  #
24
47
  # The matcher subscribes to `<namespace>.entry.created` for the duration of
25
- # the block, captures every fired event, and asserts that at least one event
48
+ # the block, on whichever channel `StandardLedger::EventEmitter` emits through
49
+ # (`Rails.event` on Rails 8.1+, `ActiveSupport::Notifications` otherwise),
50
+ # captures every fired event, and asserts that at least one event
26
51
  # matched the expected class (and, when chained, the expected `kind`,
27
52
  # `targets`, and `attrs`). The notification namespace is read from
28
53
  # `StandardLedger.config.notification_namespace`, so a host that customised
@@ -71,10 +96,35 @@ RSpec::Matchers.define :post_ledger_entry do |entry_class|
71
96
  # Helpers
72
97
  # ----------------------------------------------------------------------
73
98
 
99
+ # Listens on the same channel `EventEmitter.emit` picks. Listening only on
100
+ # AS::Notifications meant that on Rails 8.1 (where emit goes through
101
+ # `Rails.event`) the matcher saw nothing — every positive expectation
102
+ # failed and every negated one passed vacuously.
74
103
  def capture_entry_created_events(&block)
104
+ if StandardLedger::EventEmitter.rails_event_available?
105
+ capture_via_rails_event(&block)
106
+ else
107
+ capture_via_notifications(&block)
108
+ end
109
+ end
110
+
111
+ def capture_via_rails_event(&block)
112
+ bus = ::Rails.event
113
+ collector = StandardLedger::RSpec::RailsEventCollector.new(notification_event_name)
114
+ bus.subscribe(collector)
115
+
116
+ begin
117
+ block.call
118
+ ensure
119
+ bus.unsubscribe(collector)
120
+ end
121
+
122
+ collector.payloads
123
+ end
124
+
125
+ def capture_via_notifications(&block)
75
126
  events = []
76
- name = notification_event_name
77
- subscriber = ActiveSupport::Notifications.subscribe(name) do |*args|
127
+ subscriber = ActiveSupport::Notifications.subscribe(notification_event_name) do |*args|
78
128
  events << ActiveSupport::Notifications::Event.new(*args).payload
79
129
  end
80
130
 
@@ -1,3 +1,3 @@
1
1
  module StandardLedger
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard_ledger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaryl Sim