philiprehberger-state_machine 0.7.0 → 0.8.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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +8 -5
- data/lib/philiprehberger/state_machine/instance_methods.rb +30 -0
- data/lib/philiprehberger/state_machine/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 885a98621c6e7398bd5ae50b824fd6cc439c5b009fb26bbd648cf8fe46205127
|
|
4
|
+
data.tar.gz: 211673e70044114428a3624a5372da6cb5e419bde101b7fd93a98b2d9a7b8244
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8d7e14bbf7d1d91d8052fb0ccb75d1097e928137d88d9965366acd924602299a89f83b7feb0306899b39aaeefdcad5dc00b575d11042b6985ad9249d319a93b7
|
|
7
|
+
data.tar.gz: c8463b4fede47754b81bf508b82cfaf6a71f84d825b2aaf047fac2f46b8da69de0d199b990206674772797d6f2851e234d7e43e562b314dab2a6858bddd16155
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.0] - 2026-05-08
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `#can_transition_to?(state, **payload)` — returns `true` when any currently-fireable event would land the machine in `state`. Honours guards (a guarded-out transition reports `false`) and raises `ArgumentError` for unknown states. Useful for UI gating without hand-rolling the per-event lookup.
|
|
14
|
+
|
|
10
15
|
## [0.7.0] - 2026-04-24
|
|
11
16
|
|
|
12
17
|
### Added
|
data/README.md
CHANGED
|
@@ -114,11 +114,13 @@ Query the state machine at runtime:
|
|
|
114
114
|
```ruby
|
|
115
115
|
order = Order.new
|
|
116
116
|
|
|
117
|
-
order.pending?
|
|
118
|
-
order.paid?
|
|
119
|
-
order.can_pay?
|
|
120
|
-
order.can_ship?
|
|
121
|
-
order.allowed_transitions
|
|
117
|
+
order.pending? # => true
|
|
118
|
+
order.paid? # => false
|
|
119
|
+
order.can_pay? # => true
|
|
120
|
+
order.can_ship? # => false
|
|
121
|
+
order.allowed_transitions # => [:pay]
|
|
122
|
+
order.can_transition_to?(:paid) # => true
|
|
123
|
+
order.can_transition_to?(:shipped) # => false (no event leads there from :pending)
|
|
122
124
|
```
|
|
123
125
|
|
|
124
126
|
### State History
|
|
@@ -339,6 +341,7 @@ order.stuck? # => false
|
|
|
339
341
|
| `#current_state` | Returns the current state as a symbol |
|
|
340
342
|
| `#can_X?(**payload)` | Returns true if event X can fire from the current state (including guards) |
|
|
341
343
|
| `#allowed_transitions(**payload)` | Returns an array of event names that can fire from the current state |
|
|
344
|
+
| `#can_transition_to?(state, **payload)` | Returns true if any currently-fireable event would land the machine in `state` (honours guards; raises ArgumentError for unknown states) |
|
|
342
345
|
| `#X!(**payload)` | Fire event X with optional payload, or raise `InvalidTransition` |
|
|
343
346
|
| `#X(**payload)` | Fire event X with optional payload, returns true on success, false on failure |
|
|
344
347
|
| `#X?` | Returns true if current state is X |
|
|
@@ -251,6 +251,36 @@ module Philiprehberger
|
|
|
251
251
|
true
|
|
252
252
|
end.keys
|
|
253
253
|
end
|
|
254
|
+
|
|
255
|
+
# Whether any currently-fireable event would land the machine in `state`.
|
|
256
|
+
# Honours guards (a guarded-out transition reports false). Useful for UI
|
|
257
|
+
# gating without hand-rolling the per-event lookup.
|
|
258
|
+
#
|
|
259
|
+
# @param state [Symbol] the candidate target state
|
|
260
|
+
# @param payload [Hash] keyword payload forwarded to guards that accept it
|
|
261
|
+
# @return [Boolean]
|
|
262
|
+
# @raise [ArgumentError] if `state` is not declared on the machine
|
|
263
|
+
klass.define_method(:can_transition_to?) do |state, **payload|
|
|
264
|
+
unless definition.all_states.include?(state)
|
|
265
|
+
raise ArgumentError, "Unknown state: #{state.inspect}"
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
definition.events.any? do |_name, transitions|
|
|
269
|
+
transition = transitions.find { |t| t.matches?(current_state) && t.to == state }
|
|
270
|
+
next false unless transition
|
|
271
|
+
|
|
272
|
+
if transition.guard
|
|
273
|
+
guard_result = if transition.guard.arity.zero?
|
|
274
|
+
instance_exec(&transition.guard)
|
|
275
|
+
else
|
|
276
|
+
instance_exec(**payload, &transition.guard)
|
|
277
|
+
end
|
|
278
|
+
next false unless guard_result
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
true
|
|
282
|
+
end
|
|
283
|
+
end
|
|
254
284
|
end
|
|
255
285
|
end
|
|
256
286
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: philiprehberger-state_machine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Philip Rehberger
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-05-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A minimal state machine for Ruby objects. Define states, events, transitions,
|
|
14
14
|
guard conditions, and callbacks with a clean DSL. Works with any Ruby class — no
|