actionable-rb 1.9.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 +7 -0
- data/.claude-plugin/marketplace.json +15 -0
- data/.claude-plugin/plugin.json +9 -0
- data/.rspec +3 -0
- data/AGENTS.md +150 -0
- data/CHANGELOG.md +766 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +555 -0
- data/UPGRADING.md +957 -0
- data/USAGE.md +1291 -0
- data/docs/getting_started.md +611 -0
- data/lib/actionable/action.rb +1220 -0
- data/lib/actionable/batch_result.rb +92 -0
- data/lib/actionable/errors.rb +36 -0
- data/lib/actionable/history.rb +91 -0
- data/lib/actionable/input_dispatch.rb +94 -0
- data/lib/actionable/job.rb +157 -0
- data/lib/actionable/measurement.rb +64 -0
- data/lib/actionable/rails/after_commit.rb +142 -0
- data/lib/actionable/rails/proxy_validator.rb +59 -0
- data/lib/actionable/rails/transactions.rb +95 -0
- data/lib/actionable/rails.rb +24 -0
- data/lib/actionable/railtie.rb +10 -0
- data/lib/actionable/rbs.rb +502 -0
- data/lib/actionable/registry.rb +64 -0
- data/lib/actionable/result.rb +166 -0
- data/lib/actionable/results/failure.rb +43 -0
- data/lib/actionable/results/skipped.rb +30 -0
- data/lib/actionable/results/success.rb +14 -0
- data/lib/actionable/rspec/coverage/report.rb +264 -0
- data/lib/actionable/rspec/coverage/tracker.rb +330 -0
- data/lib/actionable/rspec/coverage.rb +45 -0
- data/lib/actionable/rspec/matchers.rb +266 -0
- data/lib/actionable/rspec/stubs.rb +250 -0
- data/lib/actionable/rspec.rb +40 -0
- data/lib/actionable/rubocop/config.yml +8 -0
- data/lib/actionable/rubocop/cop/actionable/verb_not_last.rb +62 -0
- data/lib/actionable/rubocop/plugin.rb +31 -0
- data/lib/actionable/rubocop.rb +25 -0
- data/lib/actionable/runner.rb +300 -0
- data/lib/actionable/steps/action.rb +76 -0
- data/lib/actionable/steps/base.rb +107 -0
- data/lib/actionable/steps/case.rb +124 -0
- data/lib/actionable/steps/method.rb +39 -0
- data/lib/actionable/steps.rb +27 -0
- data/lib/actionable/value_match.rb +22 -0
- data/lib/actionable/verb_position.rb +574 -0
- data/lib/actionable/version.rb +6 -0
- data/lib/actionable-rb.rb +6 -0
- data/lib/actionable.rb +59 -0
- data/sig/actionable/dsl.rbs +42 -0
- data/sig/actionable/rails.rbs +16 -0
- data/sig/actionable.rbs +2593 -0
- data/skills/actionable/SKILL.md +214 -0
- metadata +132 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: actionable
|
|
3
|
+
description: Author, edit, and debug Actionable service objects — declaring steps, choosing control-flow verbs (succeed/fail/fail_with/skip and their bang forms), wiring typed input/output schemas (including discriminated input via input_for), running over a collection with run_each, composing nested actions and case branches, lifecycle hooks, history/sampled measurement, serializing results (to_h/to_api_h), and the optional Rails/RSpec/job adapters.
|
|
4
|
+
when_to_use: Use when defining or modifying a class that inherits from Actionable::Action (any step / case_step / on_success / output / input / input_for declaration), when choosing how a step should record its outcome, when running an action over a collection, when debugging why a run failed/skipped or an output wasn't captured, when mapping a result to an HTTP/job response, when testing an action with the perform_actionable matcher, or when upgrading the actionable gem to a newer version.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Working with Actionable
|
|
8
|
+
|
|
9
|
+
Actionable builds **service objects**: declare an ordered list of **steps** on an
|
|
10
|
+
`Actionable::Action` subclass, implement each as a method, and run it. A run
|
|
11
|
+
returns one value object — `Success`, `Failure`, or `Skipped` — with `code`,
|
|
12
|
+
`message`, `errors`, a typed `output`, and a `history`.
|
|
13
|
+
|
|
14
|
+
## Read the bundled reference first
|
|
15
|
+
|
|
16
|
+
The gem ships a dense, example-first reference. Read it before answering a
|
|
17
|
+
non-trivial question — it matches the installed version:
|
|
18
|
+
|
|
19
|
+
- Run `bundle show actionable` and open `USAGE.md` at that path, or
|
|
20
|
+
- https://github.com/Paymentbox-com/actionable/blob/main/USAGE.md
|
|
21
|
+
|
|
22
|
+
This skill is the **workflow and the mistakes to avoid**; `USAGE.md` is the catalog.
|
|
23
|
+
|
|
24
|
+
## Defining an action
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
class CreateInvoice < Actionable::Action
|
|
28
|
+
input { required :amount, :integer } # typed .run kwargs (optional block)
|
|
29
|
+
output { required :invoice, :string } # declared, typed result payload
|
|
30
|
+
|
|
31
|
+
step :validate
|
|
32
|
+
step :build
|
|
33
|
+
|
|
34
|
+
def validate
|
|
35
|
+
fail!(:invalid_amount) unless input.amount.positive?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def build
|
|
39
|
+
@invoice = "INV-#{input.amount}" # ivar matching an output field is captured
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
result = CreateInvoice.run(amount: 10)
|
|
44
|
+
result.success? # => true
|
|
45
|
+
result.invoice # => "INV-10" (delegates to result.output.invoice)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
When asked to build one:
|
|
49
|
+
|
|
50
|
+
1. Declare `input`/`output` schemas if the action has a typed contract; reach for
|
|
51
|
+
`input.field` rather than a custom `initialize`.
|
|
52
|
+
2. Add `step :name` in order; implement each as a method.
|
|
53
|
+
3. Inside steps, record the outcome with a control-flow verb (below). Setting an
|
|
54
|
+
ivar named like an `output` field is enough to surface it — no explicit expose.
|
|
55
|
+
4. Run `bin/rspec` / `bundle exec rake` and test with `perform_actionable`.
|
|
56
|
+
|
|
57
|
+
## Choosing a control-flow verb
|
|
58
|
+
|
|
59
|
+
| Want to… | Use |
|
|
60
|
+
|----------|-----|
|
|
61
|
+
| Succeed and keep running | `succeed(message = nil, **output)` |
|
|
62
|
+
| Record an error, keep running | `fail(code, message = nil, **errors)` |
|
|
63
|
+
| Fail with a FieldStruct's errors | `fail_with(struct, code: :invalid, message: nil)` |
|
|
64
|
+
| Mark "nothing to do" (with optional output) | `skip(code = :skipped, message = nil, **output)` |
|
|
65
|
+
| Same, but stop the pipeline now | `succeed!` / `fail!` / `fail_with!` / `skip!` |
|
|
66
|
+
| Stop, keep whatever was recorded | `halt!` |
|
|
67
|
+
|
|
68
|
+
- **Skip is not failure.** Use `skip!` when a precondition isn't ready / there's
|
|
69
|
+
nothing to do — not `fail!`. A skip is `ok?` (won't read as an error) but
|
|
70
|
+
distinct from success (`skipped?`). Use `ok?` for "didn't fail" checks. `skip`
|
|
71
|
+
takes `**output` (like `succeed`), so an idempotent hit can return the existing
|
|
72
|
+
record's id.
|
|
73
|
+
- `fail_with(struct, code:)` records a failure carrying `struct`'s validation
|
|
74
|
+
errors — for validating a side FieldStruct in a step.
|
|
75
|
+
- **Declare failure codes** with `fails :refused, 'message', kind: :rejected`.
|
|
76
|
+
The keywords are neutral metadata the gem passes through to
|
|
77
|
+
`result.metadata`. Once any code is declared, failing with an undeclared one
|
|
78
|
+
raises `DefinitionError` (`:invalid_input` / `:invalid_output` are exempt).
|
|
79
|
+
`fail`'s keywords after the message are only ever errors, so an error on
|
|
80
|
+
`kind` stays an error.
|
|
81
|
+
- **Declare skip codes** with `skips :not_ready, 'message', retry: true`, read
|
|
82
|
+
back as `result.metadata` on the skip. Once any skip code is declared,
|
|
83
|
+
skipping with an undeclared one raises `DefinitionError`, the default
|
|
84
|
+
`:skipped` included (nothing is exempt).
|
|
85
|
+
- Plain verbs don't halt; last write wins. Bang verbs halt.
|
|
86
|
+
- **A plain `fail` / `fail_with` / `skip` / `succeed` must be the last
|
|
87
|
+
expression of its step or hook method** (or `return fail(...)`). `fail :x if bad?` followed by more
|
|
88
|
+
code raises `DefinitionError` on the action's first run — that's a `fail!`
|
|
89
|
+
missing its bang. The opt-in RuboCop cop `Actionable/VerbNotLast`
|
|
90
|
+
(`plugins: [{actionable-rb: {require_path: actionable/rubocop}}]`) flags it.
|
|
91
|
+
`Actionable.verb_position_check = false` turns the first-run check off (an
|
|
92
|
+
upgrade escape hatch; the cop is then the only guard). Don't reach for it to
|
|
93
|
+
silence an offense: fix the verb.
|
|
94
|
+
- `fail` / `skip` codes must be identifiers (`:card_expired`, `:ok?`); a
|
|
95
|
+
sentence raises `ArgumentError`.
|
|
96
|
+
- To signal a real bug, `raise` — exceptions propagate, they aren't caught.
|
|
97
|
+
**Never `fail 'message'` for that:** inside an action `fail` is the gem's
|
|
98
|
+
verb, not `Kernel#fail`: a sentence code raises `ArgumentError`, and a
|
|
99
|
+
one-word string (`fail 'boom'`) records a `Failure` with code `:boom` and
|
|
100
|
+
the run keeps going (a later `succeed` erases it).
|
|
101
|
+
|
|
102
|
+
```ruby
|
|
103
|
+
def charge
|
|
104
|
+
fail 'gateway down' # WRONG: not an exception; raises ArgumentError (not an identifier code)
|
|
105
|
+
raise GatewayError, 'down' # a bug / unexpected condition: propagates
|
|
106
|
+
fail!(:gateway_down, 'down') # an expected failure outcome: records and halts
|
|
107
|
+
end
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Composition
|
|
111
|
+
|
|
112
|
+
- **Nested action:** `step Notify, input: %i[invoice], expose: %i[receipt]`. A
|
|
113
|
+
child failure fails the parent with its code, message, errors and metadata
|
|
114
|
+
intact; a child skip continues it. A parent that declares failures must
|
|
115
|
+
declare its children's failure codes too, but never their skip codes.
|
|
116
|
+
- **Branch:** `case_step :status do on 'active', :handle; default :other end`
|
|
117
|
+
(matches by `==`, `Regexp`, or Array membership).
|
|
118
|
+
- **Hooks:** `on_success` / `on_failure` / `on_skip` / `always` run after the
|
|
119
|
+
main steps by outcome, inside any `transactional` transaction. With the Rails
|
|
120
|
+
adapter, `after_commit :method` (ActiveRecord >= 7.2) runs only after the
|
|
121
|
+
outermost transaction commits a successful run — the place for emails,
|
|
122
|
+
webhooks and enqueues. It can't change the result and isn't in the history.
|
|
123
|
+
A bang verb in an outcome hook stops the rest of that category, but `always`
|
|
124
|
+
hooks still run and see the adopted result — keep cleanup/audit in `always`.
|
|
125
|
+
- **Override by redeclaring:** a second `step :x` / `case_step :x` / `step
|
|
126
|
+
Child` / hook with the same name (same class or a subclass) replaces the
|
|
127
|
+
earlier one's options and keeps its position — last declaration wins. There
|
|
128
|
+
is no removal; guard an inherited step off with `if:` / `unless:`.
|
|
129
|
+
- **Discriminated input:** `input_for(:event_type) { on 'sale', SaleShape;
|
|
130
|
+
default UnknownShape }` picks the input schema at run time from a discriminator
|
|
131
|
+
(typed polymorphic input). An unmatched value with no `default` →
|
|
132
|
+
`Failure(:invalid_input)`.
|
|
133
|
+
- **Batch:** `Action.run_each(items) { |i| {…} }` runs once per item and returns a
|
|
134
|
+
`BatchResult` (`all_ok?` / `any_failure?` / `partial?`, `to_api_h`).
|
|
135
|
+
|
|
136
|
+
## Mistakes to avoid
|
|
137
|
+
|
|
138
|
+
- **Reserved output field names raise `Actionable::DefinitionError`.** An
|
|
139
|
+
`output` field named `code`/`message`/`output`/`history`/`errors`/`metadata`
|
|
140
|
+
(result attributes) or `result`/`input` (reserved ivars) is rejected when declared —
|
|
141
|
+
pick another name. (Input fields are fine; they're read via `input.x`.)
|
|
142
|
+
- **A missing step method raises `DefinitionError` at run start**, naming the
|
|
143
|
+
action and method — implement every declared step / hook / case method.
|
|
144
|
+
- **A successful run must satisfy its declared output**, or it becomes
|
|
145
|
+
`Failure(:invalid_output)`. Failures/skips capture output best-effort and are
|
|
146
|
+
not validated — so don't rely on output fields being present after a skip.
|
|
147
|
+
- **`fail` shadows `Kernel#fail`** in every instance method of an action (see
|
|
148
|
+
the verb section). Use `raise` for exceptions, `fail!(:code)` to stop with a
|
|
149
|
+
failure.
|
|
150
|
+
- **Don't `require 'actionable/rails'` in the core path.** Transactions and
|
|
151
|
+
`ProxyValidator` are opt-in; the core never loads `active_*`.
|
|
152
|
+
|
|
153
|
+
To inspect an action's shape (for tooling or to reason about it), call
|
|
154
|
+
`SomeAction.describe` — a Hash of its name, input/output, steps, declared
|
|
155
|
+
failures, hooks, measure, and transaction config (or `describe_text` for a readable summary).
|
|
156
|
+
|
|
157
|
+
## Beyond a single run
|
|
158
|
+
|
|
159
|
+
- **Serialize a result:** `result.to_h` (plain Hash) or
|
|
160
|
+
`result.to_api_h(index:)` (compact HTTP/batch element: `index`, `status`,
|
|
161
|
+
`id`, `errors`) — don't hand-map in controllers.
|
|
162
|
+
- **Background jobs (`require 'actionable/job'`):** `include
|
|
163
|
+
Actionable::Job::Mixin` into a Sidekiq/ActiveJob job and call
|
|
164
|
+
`run_actionable(SomeAction, **kwargs)` in `perform`. A success/skip acks; a
|
|
165
|
+
transient failure raises `RetryableFailure` (queue retries); a permanent-code
|
|
166
|
+
failure is discarded; a genuine exception propagates. Declared `retry:`
|
|
167
|
+
metadata is ignored unless the action calls `honor_retry_metadata`; then
|
|
168
|
+
`retry: true` retries (failures and skips) and `retry: false` doesn't.
|
|
169
|
+
- **Prod observability:** `measure :sampled, rate: 0.1` records history on a
|
|
170
|
+
fraction of runs (between `:all` and `:none`).
|
|
171
|
+
|
|
172
|
+
## Upgrading the gem
|
|
173
|
+
|
|
174
|
+
When asked to bump actionable, follow the gem's `UPGRADING.md` (next to
|
|
175
|
+
`USAGE.md` in `bundle show actionable`, or
|
|
176
|
+
https://github.com/Paymentbox-com/actionable/blob/main/UPGRADING.md) instead
|
|
177
|
+
of recalling changes. In short:
|
|
178
|
+
|
|
179
|
+
1. Read the from/to versions (`Gemfile.lock`) and only the guide's sections
|
|
180
|
+
between them.
|
|
181
|
+
2. Bump field_struct first when the target needs it (>= 0.12 from 1.6.0) and
|
|
182
|
+
follow its UPGRADING.md.
|
|
183
|
+
3. Bump actionable; check `rg --pcre2-version`, then run the Finds the guide
|
|
184
|
+
lists under "Which Finds to run" (silent changes) even on a green suite.
|
|
185
|
+
4. Enable the `Actionable/VerbNotLast` cop (list every app base class defined in
|
|
186
|
+
its own file in `ActionBaseClasses`) and run
|
|
187
|
+
`bundle exec rubocop --only Actionable/VerbNotLast`.
|
|
188
|
+
5. Apply each **Fix**; set `Actionable.verb_position_check = false` only in
|
|
189
|
+
`spec_helper` for a baseline, and never leave it behind.
|
|
190
|
+
6. Regenerate owned RBS with `Actionable::RBS.generate`.
|
|
191
|
+
7. Run the suite with the check on.
|
|
192
|
+
8. Report what was fixed, what was reviewed by hand (entries with no
|
|
193
|
+
reliable Find), and residual behaviour risks.
|
|
194
|
+
|
|
195
|
+
## Testing (`require 'actionable/rspec'`)
|
|
196
|
+
|
|
197
|
+
```ruby
|
|
198
|
+
expect(CreateInvoice).to perform_actionable(amount: 10).and_succeed
|
|
199
|
+
expect(CreateInvoice).to perform_actionable(amount: 0).and_fail(:invalid_amount)
|
|
200
|
+
expect(Sync).to perform_actionable.and_skip(:not_ready)
|
|
201
|
+
|
|
202
|
+
allow_actionable_failure(CreateInvoice, code: :invalid_amount) # stub without running
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
On an action that declares failures, a stubbed failure carries the declared
|
|
206
|
+
metadata for its code, and a stub or `and_fail` with an undeclared code raises
|
|
207
|
+
`ArgumentError`.
|
|
208
|
+
|
|
209
|
+
**Outcome coverage** (`require 'actionable/rspec/coverage'`) lists, at the end
|
|
210
|
+
of the suite, each action's outcomes no spec reached: success, every declared
|
|
211
|
+
failure and every declared skip. Only a real run counts, so a stub doesn't
|
|
212
|
+
cover anything. When a project sets `Actionable::Coverage.baseline`, a new
|
|
213
|
+
declaration (`fails :x`) needs a spec that reaches it, or an entry in the
|
|
214
|
+
baseline file; the failure message names the exact line to add or remove.
|
metadata
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: actionable-rb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.9.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Adrian Madrid
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: field_struct
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.12'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0.12'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: oj
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '3.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '3.0'
|
|
40
|
+
description: |
|
|
41
|
+
Actionable encapsulates business logic as an ordered sequence of steps that
|
|
42
|
+
return a single typed result. Pure-Ruby core (Rails transactions and validators
|
|
43
|
+
are an optional adapter); inputs and outputs are typed via field_struct; full RBS
|
|
44
|
+
signatures via Sord + YARD.
|
|
45
|
+
email:
|
|
46
|
+
- amadrid@pmtbox.com
|
|
47
|
+
executables: []
|
|
48
|
+
extensions: []
|
|
49
|
+
extra_rdoc_files: []
|
|
50
|
+
files:
|
|
51
|
+
- ".claude-plugin/marketplace.json"
|
|
52
|
+
- ".claude-plugin/plugin.json"
|
|
53
|
+
- ".rspec"
|
|
54
|
+
- AGENTS.md
|
|
55
|
+
- CHANGELOG.md
|
|
56
|
+
- CODE_OF_CONDUCT.md
|
|
57
|
+
- LICENSE.txt
|
|
58
|
+
- README.md
|
|
59
|
+
- UPGRADING.md
|
|
60
|
+
- USAGE.md
|
|
61
|
+
- docs/getting_started.md
|
|
62
|
+
- lib/actionable-rb.rb
|
|
63
|
+
- lib/actionable.rb
|
|
64
|
+
- lib/actionable/action.rb
|
|
65
|
+
- lib/actionable/batch_result.rb
|
|
66
|
+
- lib/actionable/errors.rb
|
|
67
|
+
- lib/actionable/history.rb
|
|
68
|
+
- lib/actionable/input_dispatch.rb
|
|
69
|
+
- lib/actionable/job.rb
|
|
70
|
+
- lib/actionable/measurement.rb
|
|
71
|
+
- lib/actionable/rails.rb
|
|
72
|
+
- lib/actionable/rails/after_commit.rb
|
|
73
|
+
- lib/actionable/rails/proxy_validator.rb
|
|
74
|
+
- lib/actionable/rails/transactions.rb
|
|
75
|
+
- lib/actionable/railtie.rb
|
|
76
|
+
- lib/actionable/rbs.rb
|
|
77
|
+
- lib/actionable/registry.rb
|
|
78
|
+
- lib/actionable/result.rb
|
|
79
|
+
- lib/actionable/results/failure.rb
|
|
80
|
+
- lib/actionable/results/skipped.rb
|
|
81
|
+
- lib/actionable/results/success.rb
|
|
82
|
+
- lib/actionable/rspec.rb
|
|
83
|
+
- lib/actionable/rspec/coverage.rb
|
|
84
|
+
- lib/actionable/rspec/coverage/report.rb
|
|
85
|
+
- lib/actionable/rspec/coverage/tracker.rb
|
|
86
|
+
- lib/actionable/rspec/matchers.rb
|
|
87
|
+
- lib/actionable/rspec/stubs.rb
|
|
88
|
+
- lib/actionable/rubocop.rb
|
|
89
|
+
- lib/actionable/rubocop/config.yml
|
|
90
|
+
- lib/actionable/rubocop/cop/actionable/verb_not_last.rb
|
|
91
|
+
- lib/actionable/rubocop/plugin.rb
|
|
92
|
+
- lib/actionable/runner.rb
|
|
93
|
+
- lib/actionable/steps.rb
|
|
94
|
+
- lib/actionable/steps/action.rb
|
|
95
|
+
- lib/actionable/steps/base.rb
|
|
96
|
+
- lib/actionable/steps/case.rb
|
|
97
|
+
- lib/actionable/steps/method.rb
|
|
98
|
+
- lib/actionable/value_match.rb
|
|
99
|
+
- lib/actionable/verb_position.rb
|
|
100
|
+
- lib/actionable/version.rb
|
|
101
|
+
- sig/actionable.rbs
|
|
102
|
+
- sig/actionable/dsl.rbs
|
|
103
|
+
- sig/actionable/rails.rbs
|
|
104
|
+
- skills/actionable/SKILL.md
|
|
105
|
+
homepage: https://github.com/Paymentbox-com/actionable
|
|
106
|
+
licenses:
|
|
107
|
+
- MIT
|
|
108
|
+
metadata:
|
|
109
|
+
allowed_push_host: https://rubygems.org
|
|
110
|
+
homepage_uri: https://github.com/Paymentbox-com/actionable
|
|
111
|
+
source_code_uri: https://github.com/Paymentbox-com/actionable
|
|
112
|
+
changelog_uri: https://github.com/Paymentbox-com/actionable/blob/main/CHANGELOG.md
|
|
113
|
+
rubygems_mfa_required: 'true'
|
|
114
|
+
default_lint_roller_plugin: Actionable::RubocopPlugin
|
|
115
|
+
rdoc_options: []
|
|
116
|
+
require_paths:
|
|
117
|
+
- lib
|
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
|
+
requirements:
|
|
120
|
+
- - ">="
|
|
121
|
+
- !ruby/object:Gem::Version
|
|
122
|
+
version: 3.2.0
|
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
|
+
requirements:
|
|
125
|
+
- - ">="
|
|
126
|
+
- !ruby/object:Gem::Version
|
|
127
|
+
version: '0'
|
|
128
|
+
requirements: []
|
|
129
|
+
rubygems_version: 4.0.20
|
|
130
|
+
specification_version: 4
|
|
131
|
+
summary: Simple, typed, composable Ruby service objects.
|
|
132
|
+
test_files: []
|