Class: Plushie::State
- Inherits:
-
Object
- Object
- Plushie::State
- Defined in:
- lib/plushie/state.rb
Overview
Path-based state management with revision tracking and transactions.
A lightweight wrapper around a plain hash that tracks a monotonically increasing revision number on every mutation. Useful for detecting changes and implementing optimistic concurrency.
== Transactions
+begin_transaction+ captures a snapshot of the current data and revision. Subsequent mutations increment the revision as usual. +commit_transaction+ finalises the transaction (bumping the revision once from the pre-transaction value). +rollback_transaction+ restores the snapshot exactly.
Defined Under Namespace
Classes: Container
Class Method Summary collapse
-
.begin_transaction(state) ⇒ Container, Array(:error, Symbol)
Begins a transaction by capturing the current data and revision.
-
.commit_transaction(state) ⇒ Container
Commits the active transaction, setting the revision to one past the pre-transaction value.
-
.from_hash(data) ⇒ Container
Creates a new state from an existing hash.
-
.get(state, path) ⇒ Object
Reads the value at +path+ in the state data.
-
.new(**data) ⇒ Container
Creates a new state container wrapping +data+.
-
.put(state, path, value) ⇒ Container
Sets the value at +path+ to +value+, incrementing the revision.
-
.revision(state) ⇒ Integer
Returns the current revision number.
-
.rollback_transaction(state) ⇒ Container
Rolls back the active transaction, restoring the data and revision to their pre-transaction values.
-
.update(state, path) {|current_value| ... } ⇒ Container
Applies +block+ to the value at +path+, incrementing the revision.
Class Method Details
.begin_transaction(state) ⇒ Container, Array(:error, Symbol)
Begins a transaction by capturing the current data and revision.
91 92 93 94 95 96 97 |
# File 'lib/plushie/state.rb', line 91 def self.begin_transaction(state) if state.transaction [:error, :transaction_already_active] else state.with(transaction: {data: state.data, revision: state.revision}) end end |
.commit_transaction(state) ⇒ Container
Commits the active transaction, setting the revision to one past the pre-transaction value.
104 105 106 107 |
# File 'lib/plushie/state.rb', line 104 def self.commit_transaction(state) old_rev = state.transaction[:revision] state.with(transaction: nil, revision: old_rev + 1) end |
.from_hash(data) ⇒ Container
Creates a new state from an existing hash.
42 43 44 |
# File 'lib/plushie/state.rb', line 42 def self.from_hash(data) Container.new(data: data, revision: 0, transaction: nil) end |
.get(state, path) ⇒ Object
Reads the value at +path+ in the state data. An empty path returns the entire data hash.
52 53 54 55 |
# File 'lib/plushie/state.rb', line 52 def self.get(state, path) return state.data if path.empty? state.data.dig(*path) end |
.new(**data) ⇒ Container
Creates a new state container wrapping +data+. The initial revision is 0.
34 35 36 |
# File 'lib/plushie/state.rb', line 34 def self.new(**data) Container.new(data: data, revision: 0, transaction: nil) end |
.put(state, path, value) ⇒ Container
Sets the value at +path+ to +value+, incrementing the revision.
63 64 65 66 |
# File 'lib/plushie/state.rb', line 63 def self.put(state, path, value) new_data = deep_put(state.data, path, value) state.with(data: new_data, revision: state.revision + 1) end |
.revision(state) ⇒ Integer
Returns the current revision number.
85 |
# File 'lib/plushie/state.rb', line 85 def self.revision(state) = state.revision |
.rollback_transaction(state) ⇒ Container
Rolls back the active transaction, restoring the data and revision to their pre-transaction values.
114 115 116 117 |
# File 'lib/plushie/state.rb', line 114 def self.rollback_transaction(state) snapshot = state.transaction state.with(data: snapshot[:data], revision: snapshot[:revision], transaction: nil) end |
.update(state, path) {|current_value| ... } ⇒ Container
Applies +block+ to the value at +path+, incrementing the revision. The block receives the current value and must return the new value.
76 77 78 79 |
# File 'lib/plushie/state.rb', line 76 def self.update(state, path, &block) current = get(state, path) put(state, path, block.call(current)) end |