decide.rb 0.4.1 → 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: bde47991ca269c4a20a47e138fb8eeb5d1135262a390991bb4b946daa778362d
4
- data.tar.gz: 5c3712f51013003b099ee4e3f7a568adecd92b0cd5d988c2f4140bb578f88e0c
3
+ metadata.gz: ef8d1d4fca8684c60ecb2488adc19d4f755b122124b9b593da08cf7beffa7d94
4
+ data.tar.gz: 6aacf3454c6daaff3b51aae6f420b9b892a3c2e66e344a881cceef89f68e91fd
5
5
  SHA512:
6
- metadata.gz: ae016ee97e995c8338221555a0cd444aa600a6ff2e22fa83e53fe2743747dca391392b07d032a3100cce9240978cd0605f86fb355692d0938bf0fd34560c8222
7
- data.tar.gz: 97ca74eb8729f4fbd1fdfe86e545cb428ef58974cfc7b91645ea246f0db140e0432229e2bec5e686898dd4a365e36419ea8dfd6ca903d643a6524c4db470380d
6
+ metadata.gz: 8b8439f8b22c039685579b2b5bb600df10e1f22d521dae322aec3647240725583f9a4c804c9ceb8ccac14e1cc892e173d55de7371ce22e148914c98b9c61be31
7
+ data.tar.gz: 1274953fe8087229ad4595e903634751ef3253cf66243f60842d2d43f0be0a24f9d9be3d8a4fe24f05bbe1f5f85cf0a3ecc63abd8d6ac11c26cdaed45c6d78ab
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ # 0.5.0
2
+
3
+ * Support pattern matching for commands and events
4
+ * Support passing state to decider and evolve matchers
5
+ * Remove explicit arguments for handlers
6
+ * Remove redundant bang methods - raise error in catch-all if needed
7
+ * Add Left|Right value wrappers for composition
8
+ * Use `emit` to return events in `decide`
9
+
1
10
  # 0.4.1
2
11
 
3
12
  * `define` returns new class, not object
data/README.md CHANGED
@@ -49,7 +49,7 @@ ValueDecider = Decider.define do
49
49
  initial_state State.new(value: 0)
50
50
 
51
51
  # decide command with state
52
- decide Commands::Increase do |command, state|
52
+ decide Commands::Increase do
53
53
  # return collection of events
54
54
  if state.max?
55
55
  []
@@ -58,7 +58,7 @@ ValueDecider = Decider.define do
58
58
  end
59
59
  end
60
60
 
61
- decide Commands::Decrease do |command, state|
61
+ decide Commands::Decrease do
62
62
  if state.min?
63
63
  []
64
64
  else
@@ -67,17 +67,17 @@ ValueDecider = Decider.define do
67
67
  end
68
68
 
69
69
  # evolve state with events
70
- evolve Events::ValueIncreased do |state, event|
70
+ evolve Events::ValueIncreased do
71
71
  # return new state
72
72
  state.with(value: state.value + 1)
73
73
  end
74
74
 
75
- evolve Events::ValueDecreased do |state, event|
75
+ evolve Events::ValueDecreased do
76
76
  # state is immutable Data object
77
77
  state.with(value: state.value - 1)
78
78
  end
79
79
 
80
- terminal? do |state|
80
+ terminal? do
81
81
  state <= 0
82
82
  end
83
83
  end
@@ -96,15 +96,15 @@ Right = Data.define(:value)
96
96
  left = Decider.define do
97
97
  initial_state Left.new(value: 0)
98
98
 
99
- decide Commands::LeftCommand do |command, state|
99
+ decide Commands::LeftCommand do
100
100
  [Events::LeftEvent.new(value: command.value)]
101
101
  end
102
102
 
103
- evolve Events::LeftEvent do |state, event|
103
+ evolve Events::LeftEvent do
104
104
  state.with(value: state.value + 1)
105
105
  end
106
106
 
107
- terminal? do |state|
107
+ terminal? do
108
108
  state <= 0
109
109
  end
110
110
  end
@@ -112,15 +112,15 @@ end
112
112
  right = Decider.define do
113
113
  initial_state Right.new(value: 0)
114
114
 
115
- decide Commands::RightCommand do |command, state|
115
+ decide Commands::RightCommand do
116
116
  [Events::RightEvent.new(value: command.value)]
117
117
  end
118
118
 
119
- evolve Events::RightEvent do |state, event|
119
+ evolve Events::RightEvent do
120
120
  state.with(value: state.value + 1)
121
121
  end
122
122
 
123
- terminal? do |state|
123
+ terminal? do
124
124
  state <= 0
125
125
  end
126
126
  end
@@ -128,13 +128,13 @@ end
128
128
  Composition = Decider.compose(left, right)
129
129
 
130
130
  state = Composition.initial_state
131
- #> #<data left=#<data Left value=0>, right=#<data Right value=0>>
131
+ #> #<data Decider::Pair left=#<data Left value=0>, right=#<data Right value=0>>
132
132
 
133
- events = Composition.decide(Commands::LeftCommand.new(value: 1), state)
134
- #> [#<data value=1>]
133
+ events = Composition.decide(Decider::Left.new(Commands::LeftCommand.new(value: 1)), state)
134
+ #> [#<Decider::Left value=#<data value=1>]
135
135
 
136
136
  state = events.reduce(state, &Composition.method(:evolve))
137
- #> #<data left=#<data value=1>, right=#<data value=0>>
137
+ #> #<data Decider::Pair left=#<data value=1>, right=#<data value=0>>
138
138
  ```
139
139
 
140
140
  ## Development
data/examples/decide.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # Decide
2
2
 
3
+ ## Match by command
4
+
5
+ ```ruby
6
+ Command = Data.define(:value)
7
+ State = Data.define(:value)
8
+
9
+ decider = Decider.define do
10
+ initial_state State.new(value: 5)
11
+
12
+ decide Command do
13
+ # emit events
14
+ emit Event.new(
15
+ value: command.value + state.value
16
+ )
17
+ end
18
+ end
19
+
20
+ decider.decide Command.new(value: 10), decider.initial_state
21
+ #> [Event.new(value: 15)]
22
+ ```
23
+
24
+ ## Match by command and state
25
+
26
+ ```ruby
27
+ decider = Decider.define do
28
+ initial_state :turned_off
29
+
30
+ decide :turn_on, :turned_off do
31
+ emit :turned_on
32
+ end
33
+
34
+ decide :turn_off, :turned_on do
35
+ emit :turned_off
36
+ end
37
+ end
38
+
39
+ decider.decide :turn_on, decider.initial_state
40
+ #> [:turned_on]
41
+ decider.decide :turn_off, :turned_on
42
+ #> [:turned_off]
43
+ decider.decide :turn_on, :turned_on
44
+ #> []
45
+ ```
46
+
47
+ ## Match by pattern matching
48
+
49
+ State = Data.define(:status)
50
+ TurnOn = Data.define
51
+ TurnOff = Data.define
52
+
53
+ ```ruby
54
+ decider = Decider.define do
55
+ initial_state State.new(status: :turned_off)
56
+
57
+ decide proc { [command, state] in [TurnOn, State(status: :turned_off)] } do
58
+ emit :turned_on
59
+ end
60
+
61
+ decide proc { [command, state] in [TurnOff, State(status: :turned_on)] } do
62
+ emit :turned_off
63
+ end
64
+ end
65
+
66
+ decider.decide :turn_on, decider.initial_state
67
+ #> [:turned_on]
68
+ decider.decide :turn_off, :turned_on
69
+ #> [:turned_off]
70
+ decider.decide :turn_on, :turned_on
71
+ #> []
72
+ ```
73
+
3
74
  ## Handling unknown commands
4
75
 
5
76
  ```ruby
@@ -15,11 +86,18 @@ decider.decide :unknown, decider.initial_state
15
86
  #> []
16
87
  ```
17
88
 
18
- Raise error when using `decide!`:
89
+ If you want to raise error, define a catch-all as last one:
19
90
 
20
91
  ```ruby
21
- decider.decide! :unknown, decider.initial_state
22
- #> raise ArgumentError, Unknown command
92
+ decider = Decider.define do
93
+ initial_state :initial
94
+
95
+ decide proc { true } do
96
+ raise ArgumentError, "Unknown command #{command}"
97
+ end
98
+ end
99
+ decider.decide :unknown, decider.initial_state
100
+ #> Unknown command unknown (ArgumentError)
23
101
  ```
24
102
 
25
103
  ## Commands
@@ -30,24 +108,21 @@ Commands can be primitives like symbols:
30
108
  decider = Decider.define do
31
109
  initial_state :initial
32
110
 
33
- decide :start do |command, state|
34
- case state
35
- in :initial, :stopped
36
- [:started]
37
- else
38
- []
39
- end
111
+ decide proc { [command, state] in [:start, :initial | :stopped] } do
112
+ emit :started
40
113
  end
41
114
 
42
- decide :stop do |command, state|
43
- case state
44
- in :started
45
- [:stopped]
46
- else
47
- []
48
- end
115
+ decide proc { [command, state] in [:stop, :started] } do
116
+ emit :stopped
49
117
  end
50
118
  end
119
+
120
+ decider.decide :start, decider.initial_state
121
+ #> [:started]
122
+ decider.decide :stop, :started
123
+ #> [:stopped]
124
+ decider.decider :start, :started
125
+ #> []
51
126
  ```
52
127
 
53
128
  Or any classes like [Dry::Struct](https://dry-rb.org/gems/dry-struct/) or [Data](https://rubyapi.org/3.3/o/data):
@@ -59,23 +134,47 @@ Stop = Data.define
59
134
  decider = Decider.define do
60
135
  initial_state :initial
61
136
 
62
- decide Start do |command, state|
63
- case state
64
- in :initial, :stopped
65
- [:started, command.value]
66
- else
67
- []
68
- end
137
+ decide proc { [command, state] in [Start, :initial | :stopped] } do
138
+ emit [:started, command.value]
69
139
  end
70
140
 
71
- decide Stop do |command, state|
72
- case state
73
- in :started
74
- [:stopped]
75
- else
76
- []
77
- end
141
+ decide proc { [command, state] in [Stop, [:started, _]] } do
142
+ emit :stopped
78
143
  end
79
144
  end
145
+
146
+ decider.decide Start.new(value: 10), decider.initial_state
147
+ #> [[:started, 10]]
148
+ decider.decide Stop.new, [:started, 10]
149
+ #> [:stopped]
80
150
  ```
81
151
 
152
+ ## Emitting Events
153
+
154
+ Decide can emit 0, 1 or more events:
155
+
156
+ ```ruby
157
+ decider = Decider.define do
158
+ initial_state :initial
159
+
160
+ decide :none do
161
+ # noop
162
+ end
163
+
164
+ decide :one do
165
+ emit :event
166
+ end
167
+
168
+ decide :multiple do
169
+ emit :one
170
+ emit :two
171
+ end
172
+ end
173
+
174
+ decider.decide :none, decider.initial_state
175
+ #> []
176
+ decider.decide :one, decider.initial_state
177
+ #> [:event]
178
+ decider.decide :multiple, decider.initial_state
179
+ #> [:one, :two]
180
+ ```
data/examples/infra.md ADDED
@@ -0,0 +1,15 @@
1
+ # Infra
2
+
3
+ ## In memory
4
+
5
+ ```ruby
6
+ require "decider/in_memory"
7
+
8
+ GLOBAL = Decider::InMemory.new(MyDecider)
9
+
10
+ # returns list of events
11
+ GLOBAL.handle(command)
12
+
13
+ # returns current state
14
+ GLOBAL.state
15
+ ```
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decider
4
+ class EventSourcing
5
+ def initialize(decider:, event_store:)
6
+ @decider = decider
7
+ @event_store = event_store
8
+ end
9
+
10
+ def call(command, stream_name:)
11
+ events = event_store.read.stream(stream_name)
12
+ state = events.reduce(decider.initial_state, &decider.method(:evolve))
13
+
14
+ new_events = decider.decide(command, state)
15
+
16
+ event_store.append(new_events, stream_name: stream_name, expected_version: events.count)
17
+
18
+ [new_events, events.count + new_events.count]
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :decider, :event_store
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "concurrent-ruby"
4
+
5
+ module Decider
6
+ class InMemory
7
+ def initialize(decider)
8
+ @decider = decider
9
+ @atom = Concurrent::Atom.new(decider.initial_state)
10
+ end
11
+
12
+ def call(command)
13
+ events = decider.decide(command, state)
14
+ atom.swap { |state| events.reduce(state, &decider.method(:evolve)) }
15
+ events
16
+ end
17
+
18
+ def state
19
+ atom.value
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :decider, :atom
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decider
4
+ class State
5
+ def initialize(decider:, repository:)
6
+ @decider = decider
7
+ @repository = repository
8
+ end
9
+
10
+ def call(command, key:, etag: nil)
11
+ state, etag = repository.try_load(key: key, etag: etag)
12
+
13
+ events = decider.decide(command, state)
14
+ new_state = events.reduce(state, &decider.method(:evolve))
15
+
16
+ new_etag = repository.save(new_state, key: key, etag: etag)
17
+
18
+ [events, new_etag]
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :decider, :repository
24
+ end
25
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Decider
4
- VERSION = "0.4.1"
4
+ VERSION = "0.5.1"
5
5
  end
data/lib/decider.rb CHANGED
@@ -4,82 +4,104 @@ module Decider
4
4
  StateAlreadyDefined = Class.new(StandardError)
5
5
  StateNotDefined = Class.new(StandardError)
6
6
 
7
- class Composition < Array
8
- BLANK = Object.new
9
- private_constant :BLANK
7
+ Pair = Data.define(:left, :right)
10
8
 
11
- def initialize(left, right)
12
- super([left, right]).freeze
9
+ class Left
10
+ attr_reader :value
11
+
12
+ def initialize(value)
13
+ @value = value
13
14
  end
14
15
 
15
- def with(left: BLANK, right: BLANK)
16
- Composition.new(
17
- (left == BLANK) ? self.left : left,
18
- (right == BLANK) ? self.right : right
19
- )
16
+ def deconstruct
17
+ [:left, value]
20
18
  end
21
19
 
22
- def left
23
- self[0]
20
+ def ==(other)
21
+ value == other.value
24
22
  end
23
+ end
25
24
 
26
- def right
27
- self[1]
25
+ class Right
26
+ attr_reader :value
27
+
28
+ def initialize(value)
29
+ @value = value
30
+ end
31
+
32
+ def deconstruct
33
+ [:right, value]
34
+ end
35
+
36
+ def ==(other)
37
+ value == other.value
28
38
  end
29
39
  end
30
40
 
31
41
  class Module < ::Module
32
- def initialize(initial_state:, deciders:, evolutions:, terminal:)
33
- define_method(:initial_state) do
34
- initial_state
35
- end
36
-
37
- define_method(:commands) do
38
- deciders.keys
39
- end
42
+ DECIDE_FALLBACK = proc { [nil, proc {}] }
43
+ EVOLVE_FALLBACK = proc { [nil, proc { state }] }
40
44
 
41
- define_method(:events) do
42
- evolutions.keys
45
+ Decide = Data.define(:command, :state, :_events) do
46
+ def emit(*events)
47
+ _events.push(*events)
43
48
  end
49
+ end
50
+ Evolve = Data.define(:state, :event)
51
+ Terminal = Data.define(:state)
44
52
 
45
- define_method(:decide!) do |command, state|
46
- case deciders.find { |key, _| key === command }
47
- in [_, handler]
48
- handler.call(command, state)
49
- else
50
- raise ArgumentError, "Unknown command: #{command.inspect}"
51
- end
53
+ def initialize(initial_state:, deciders:, evolutions:, terminal:)
54
+ define_method(:initial_state) do
55
+ initial_state
52
56
  end
53
57
 
54
58
  define_method(:decide) do |command, state|
55
- case deciders.find { |key, _| key === command }
56
- in [_, handler]
57
- handler.call(command, state)
58
- else
59
- []
60
- end
61
- end
62
-
63
- define_method(:evolve!) do |state, event|
64
- case evolutions.find { |key, _| key === event }
65
- in [_, handler]
66
- handler.call(state, event)
67
- else
68
- raise ArgumentError, "Unknown event: #{event.inspect}"
69
- end
59
+ context = Decide.new(command: command, state: state, _events: [])
60
+
61
+ deciders.find(DECIDE_FALLBACK) do |args, _|
62
+ case args
63
+ in [Proc => fn]
64
+ context.instance_exec(&fn)
65
+ in [ctype]
66
+ command in ^ctype
67
+ in [ctype, stype]
68
+ [command, state] in [^ctype, ^stype]
69
+ else
70
+ false
71
+ end
72
+ end => [_, handler]
73
+
74
+ context.instance_exec(&handler)
75
+ context._events
70
76
  end
71
77
 
72
78
  define_method(:evolve) do |state, event|
73
- case evolutions.find { |key, _| key === event }
74
- in [_, handler]
75
- handler.call(state, event)
76
- else
77
- state
78
- end
79
+ context = Evolve.new(state: state, event: event)
80
+
81
+ evolutions.find(EVOLVE_FALLBACK) do |args, _|
82
+ case args
83
+ in [Proc => fn]
84
+ context.instance_exec(&fn)
85
+ in [etype]
86
+ event in ^etype
87
+ in [stype, etype]
88
+ [state, event] in [^stype, ^etype]
89
+ else
90
+ false
91
+ end
92
+ end => [_, handler]
93
+
94
+ context.instance_exec(&handler)
79
95
  end
80
96
 
81
97
  define_method(:terminal?) do |state|
82
- terminal.call(state)
98
+ context = Terminal.new(state: state)
99
+
100
+ context.instance_exec(&terminal)
101
+ end
102
+
103
+ define_method(:dimap_on_state) do |fl:, fr:|
104
+ Decider.dimap_on_state(self, fl: fl, fr: fr)
83
105
  end
84
106
  end
85
107
  end
@@ -93,7 +115,7 @@ module Decider
93
115
  @initial_state = DEFAULT
94
116
  @deciders = {}
95
117
  @evolutions = {}
96
- @terminal = ->(_state) { false }
118
+ @terminal = proc { false }
97
119
  end
98
120
 
99
121
  def build(&block)
@@ -125,12 +147,12 @@ module Decider
125
147
  @initial_state = state
126
148
  end
127
149
 
128
- def decide(command, &block)
129
- deciders[command] = block
150
+ def decide(*args, &block)
151
+ deciders[args] = block
130
152
  end
131
153
 
132
- def evolve(event, &block)
133
- evolutions[event] = block
154
+ def evolve(*args, &block)
155
+ evolutions[args] = block
134
156
  end
135
157
 
136
158
  def terminal?(&block)
@@ -146,39 +168,52 @@ module Decider
146
168
 
147
169
  def self.compose(left, right)
148
170
  define do
149
- initial_state Composition.new(left.initial_state, right.initial_state)
171
+ initial_state Pair.new(
172
+ left: left.initial_state,
173
+ right: right.initial_state
174
+ )
150
175
 
151
- left.commands.each do |klass|
152
- decide klass do |command, state|
153
- left.decide(command, state.left)
154
- end
176
+ decide proc { command in [:left, _] } do
177
+ left.decide(command.value, state.left).each { emit Left.new(_1) }
155
178
  end
156
179
 
157
- right.commands.each do |klass|
158
- decide klass do |command, state|
159
- right.decide(command, state.right)
160
- end
180
+ decide proc { command in [:right, _] } do
181
+ right.decide(command.value, state.right).each { emit Right.new(_1) }
161
182
  end
162
183
 
163
- left.events.each do |klass|
164
- evolve klass do |state, event|
165
- state.with(
166
- left: left.evolve(state.left, event)
167
- )
168
- end
184
+ evolve proc { event in [:left, _] } do
185
+ state.with(
186
+ left: left.evolve(state.left, event.value)
187
+ )
169
188
  end
170
189
 
171
- right.events.each do |klass|
172
- evolve klass do |state, event|
173
- state.with(
174
- right: right.evolve(state.right, event)
175
- )
176
- end
190
+ evolve proc { event in [:right, _] } do
191
+ state.with(
192
+ right: right.evolve(state.right, event.value)
193
+ )
177
194
  end
178
195
 
179
- terminal? do |state|
196
+ terminal? do
180
197
  left.terminal?(state.left) && right.terminal?(state.right)
181
198
  end
182
199
  end
183
200
  end
201
+
202
+ def self.dimap_on_state(decider, fl:, fr:)
203
+ define do
204
+ initial_state fr.call(decider.initial_state)
205
+
206
+ decide proc { true } do
207
+ decider.decide(command, fl.call(state)).each(&method(:emit))
208
+ end
209
+
210
+ evolve proc { true } do
211
+ fr.call(decider.evolve(fl.call(state), event))
212
+ end
213
+
214
+ terminal? do
215
+ decider.terminal?(fl.call(state))
216
+ end
217
+ end
218
+ end
184
219
  end
metadata CHANGED
@@ -1,15 +1,56 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decide.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Dudulski
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-11-11 00:00:00.000000000 Z
12
- dependencies: []
10
+ date: 2025-04-12 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: concurrent-ruby
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.3'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.3'
26
+ - !ruby/object:Gem::Dependency
27
+ name: sqlite3
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 2.5.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 2.5.0
40
+ - !ruby/object:Gem::Dependency
41
+ name: ruby_event_store
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.15'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.15'
13
54
  description: Functional Event Sourcing Decider in Ruby
14
55
  email:
15
56
  - jan@dudulski.pl
@@ -25,8 +66,12 @@ files:
25
66
  - Steepfile
26
67
  - examples/decide.md
27
68
  - examples/evolve.md
69
+ - examples/infra.md
28
70
  - examples/state.md
29
71
  - lib/decider.rb
72
+ - lib/decider/event_sourcing.rb
73
+ - lib/decider/in_memory.rb
74
+ - lib/decider/state.rb
30
75
  - lib/decider/version.rb
31
76
  - sig/decider.rbs
32
77
  homepage: https://github.com/jandudulski/decide.rb
@@ -39,7 +84,6 @@ metadata:
39
84
  documentation_uri: https://github.com/jandudulski/decide.rb
40
85
  homepage_uri: https://github.com/jandudulski/decide.rb
41
86
  source_code_uri: https://github.com/jandudulski/decide.rb
42
- post_install_message:
43
87
  rdoc_options: []
44
88
  require_paths:
45
89
  - lib
@@ -54,8 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
54
98
  - !ruby/object:Gem::Version
55
99
  version: '0'
56
100
  requirements: []
57
- rubygems_version: 3.5.16
58
- signing_key:
101
+ rubygems_version: 3.6.2
59
102
  specification_version: 4
60
103
  summary: Functional Event Sourcing Decider in Ruby
61
104
  test_files: []