u-case 5.3.0 → 5.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68a2fca8a1808ae9a30ffcdca77631507d89de9fd070628442a9860ce1000fc3
4
- data.tar.gz: bcdfdac58fd882e5ed1f912e29d8decbf83971638e43acfe62e84a8697530dc9
3
+ metadata.gz: 0dd8852d56fd022780ae18b61d849649c84080c4fe2a681aca031d3b0c43b139
4
+ data.tar.gz: 8d9196aee650c25efc8bedc701cbcc1f190e14ea4c8ca97ea6f2f22b3c09259c
5
5
  SHA512:
6
- metadata.gz: ef37188a66960746af6613e98c259198e489afb75f25821d15b91cf24cc485b1153f05a80745f702e158f0fcbb0cd84733bccf7fefb0581f03d3c81dbbd69a69
7
- data.tar.gz: a89891142cbe3be3cc36ac5cdd22f257d164c47ff1b1a484768b76b9f199590dfb10725985369080a73105db23f42a2d5401ab0a6cd8f977df1cc8b9873e92aa
6
+ metadata.gz: a7b9beee649d540efdbae0553139f09fc4a9053390db61c98c5fd0a3a81569ea7ab60a6db0218f7842f38eabd90f2f0bdec86c717ee473f5692143a1ae44746d
7
+ data.tar.gz: 1ade9a482e232dfdd5a1976aeb2e47f0b2a5f129bdb965911f7cfda233b2f99f0e34fae97a3402770700bb367a32ded882b1a4b7727c5aae2d7ad0680d863c32
data/CHANGELOG.md ADDED
@@ -0,0 +1,530 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ > **Note:** This gem was originally published as `u-service` (versions 0.1.0 – 1.0.0) and renamed to `u-case` starting with `u-case 1.0.0` on 2019-09-15.
9
+
10
+ ## [5.4.0] - 2026-05-24
11
+ ### Added
12
+ - `Micro::Case.config.disable_runtime_checks` config (default `false`) to skip the gem's internal argument/contract checks for better performance in production. All checks are consolidated in `Micro::Case::Check::Enabled` (the default) and `Micro::Case::Check::Disabled` (no-ops with the same signature); the active module is swapped via `Micro::Case.check`. Measured throughput win is JIT-dependent: within noise on stock Ruby (no JIT), ~3–5% on Ruby 3.2 +YJIT, ~4–7% on Ruby 4.0 +PRISM (see `benchmarks/perfomance/runtime_checks/compare.rb`). Closes #45.
13
+ - `benchmarks/perfomance/runtime_checks/` — per-mode subprocess benchmark (`checks_enabled.rb`, `checks_disabled.rb`, `compare.rb`) demonstrating the toggle's perf effect across Ruby versions and JIT modes.
14
+
15
+ ## [5.3.1] - 2026-05-23
16
+ ### Added
17
+ - This `CHANGELOG.md`, covering the full history of the gem (from `u-service 0.1.0` through `u-case 5.3.1`) following the [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) spec.
18
+ - `changelog_uri`, `source_code_uri` and `bug_tracker_uri` entries in `spec.metadata` so RubyGems.org surfaces direct links from the gem page and tools like `bundle outdated` can deep-link to the changelog.
19
+
20
+ ## [5.3.0] - 2026-05-23
21
+ ### Added
22
+ - `Micro::Case.config.disable_safe_features` config (default `false`) to forbid `Safe` usage so a codebase can standardize on plain `rescue` for exception handling. When enabled, subclassing `Micro::Case::Safe`, calling `Micro::Cases.safe_flow(...)` or `Micro::Case::Result#on_exception` raise `Micro::Case::Error::SafeFeaturesDisabled` (closes #47, #141).
23
+ - README "Safe" section now documents how to opt out via `disable_safe_features`.
24
+
25
+ ## [5.2.1] - 2026-05-23
26
+ ### Fixed
27
+ - Propagate the parent `Micro::Case::Result` when invoking a class-level inner `flow ...`. Previously, transitions accumulated on the parent `Result` were silently dropped whenever a use case with an inner flow was invoked from another flow or chained via `Result#then`. Behavior is now unified across `Micro::Cases.flow`, `Micro::Cases.safe_flow`, `class < Micro::Case; flow ...; end` and `class < Micro::Case::Safe; flow ...; end` regardless of nesting or chaining.
28
+
29
+ ### Added
30
+ - `ruby-lsp` as a development dependency on Ruby >= 3.0.
31
+ - Flow composition matrix test suite covering all four flow constructors at 4+ nesting levels, every `Result#then` / class-level `.then` variant, the `[UseCase, defaults]` step shape, and self-referential inner flows.
32
+
33
+ ## [5.2.0] - 2026-05-23
34
+ ### Changed
35
+ - `accept:` / `reject:` attribute validation from `u-attributes` is now enabled by default. Use cases automatically fail with `:invalid_attributes` when an attribute is rejected. When combined with ActiveModel validation, `accept` runs first and ActiveModel validation only runs if every attribute is accepted (closes #90).
36
+ - Widened `u-attributes` runtime dependency to `>= 2.8, < 4.0`. On `u-attributes` 2.8 (which does not ship the Accept feature) the base behavior is unchanged; on 3.x the Accept feature is wired in automatically.
37
+ - READMEs (EN + pt-BR) now document the `accept:` / `reject:` attribute validation flow.
38
+
39
+ ### Removed
40
+ - The short-lived `Micro::Case::Config#enable_attributes_accept` toggle introduced earlier in this release cycle. It never had a working opt-out: load-time switching was defeated by load order (Rails initializers run after `require 'u-case'`) and the runtime flag only suppressed auto-failure while still mixing in `Accept`. Users who don't want the auto-failure can simply omit `accept:` / `reject:` from their attribute declarations.
41
+
42
+ ### Fixed
43
+ - Gate the `minitest` development dependency on Ruby version.
44
+
45
+ ## [5.1.0] - 2026-05-23
46
+ ### Added
47
+ - `Micro::Case::Result#keys`, `#fetch` and `#fetch_values` for `Hash`-like access to the result data (PR #127, thanks @tomascco).
48
+ - pt-BR README documentation for the new `Result` methods.
49
+
50
+ ## [5.0.0] - 2026-05-23
51
+ ### Changed
52
+ - **BREAKING:** Bumped minimum Ruby to **2.7.0** (Ruby 2.2 – 2.6 are EOL and no longer supported).
53
+ - Widened runtime dependency upper bounds so the 5.0.0 line resolves against the latest releases of its siblings: `kind` is now `>= 5.6, < 7.0` and `u-attributes` is now `>= 2.7, < 4.0`.
54
+ - Modernized the CI/test runner via Appraisal (mirroring the `solid-process` layout): per-Rails subdirectory gemfiles were replaced with an `Appraisals` file gated on `RUBY_VERSION`, the GitHub Actions matrix now covers Ruby 2.7 – 4.0+head with conditional Rails steps, and the `ENABLE_TRANSITIONS` true/false axis is preserved as a CI matrix dimension.
55
+ - Switched code coverage reporting from CodeClimate to **Qlty** (OIDC-based upload, badges updated in both READMEs).
56
+ - README polish: new header/badge layout, Ruby × Rails support matrix, refreshed compatibility table, and pt-BR typo fixes.
57
+
58
+ ### Added
59
+ - Appraisal-generated gemfiles for **Rails 8.1** and **Rails edge**.
60
+ - `bin/matrix` script and `rake matrix` task to run the full local test matrix.
61
+ - `bin/setup` script.
62
+
63
+ ### Removed
64
+ - Per-Rails subdirectory gemfiles under `gemfiles/rails_5.2…rails_edge/` (replaced by Appraisal).
65
+ - `pry-byebug` from the test helper (dev-only convenience, no longer required).
66
+
67
+ ### Security
68
+ - Hardened the GitHub Actions workflow per `zizmor` findings: least-privilege `contents: read` permissions on the test job and `persist-credentials: false` on `actions/checkout` (#135).
69
+
70
+ ## [4.5.2] - 2022-12-05
71
+ ### Added
72
+ - Add Ruby 3.1 to the test matrix.
73
+
74
+ ### Changed
75
+ - Migrate CI from Travis CI to GitHub Actions.
76
+
77
+ ### Fixed
78
+ - Rename `Micro::Case::Utils::Hashes.respond_to?` to `hash_respond_to?` so it no longer overrides Ruby's default `respond_to?`.
79
+ - Return the generated flow-step class explicitly so flow definitions stay compatible with Ruby 3.1.
80
+ - Restore `Micro::Cases.map` behavior on Ruby 2.5 (avoid `return` inside the inner lambda).
81
+
82
+ ## [4.5.1] - 2021-06-08
83
+ ### Fixed
84
+ - Stop invoking `on_unknown` after a matching `on_exception` hook has already handled the result.
85
+
86
+ ## [4.5.0] - 2021-06-08
87
+ ### Changed
88
+ - Bump the required `kind` runtime dependency to `>= 5.6, < 6.0`.
89
+
90
+ ## [4.4.0] - 2021-06-08
91
+ ### Changed
92
+ - Optimize `Micro::Case::With::ActiveModelValidation`: validations now run lazily via `errors.present?` during the call instead of eagerly in `initialize`, and the redundant `respond_to?(:run_validations!)` check is gone.
93
+
94
+ ## [4.3.0] - 2021-02-22
95
+ ### Added
96
+ - `Micro::Case#Check(type = nil, result: nil) { ... }` helper that turns a truthy/falsy block into a typed `Success`/`Failure` (defaulting to `:check_ok` / `:check_fail`).
97
+ - `Result#then` now accepts a `Symbol`/`String`, calling the matching instance method on the source use case as the next step.
98
+
99
+ ### Changed
100
+ - Bump runtime dependencies: `kind` to `>= 4.0, < 6.0` and `u-attributes` to `>= 2.7, < 3.0`.
101
+ - Make the test suite Ruby 3.0 compatible.
102
+
103
+ ### Removed
104
+ - Stop registering `Micro::Case` and `Micro::Case::Result` with `Kind::Types`, dropping the `Kind::Of::Micro::Case` / `Kind::Of::Micro::Case::Result` validators.
105
+
106
+ ## [4.2.2] - 2020-12-04
107
+ ### Fixed
108
+ - Fix the output returned when invoking a use case with a block — the block's wrapper output is now propagated as the call's return value via the new `Result::Wrapper#output`.
109
+
110
+ ## [4.2.1] - 2020-10-21
111
+ ### Fixed
112
+ - Make `Micro::Case`, `Micro::Case::Result`, and `Micro::Cases::Flow` `#inspect` strings start with `#<...>` and collapse recursive inspect output to `#<Class: ...>`.
113
+
114
+ ## [4.2.0] - 2020-10-19
115
+ ### Added
116
+ - `Micro::Case#transaction(adapter = :activerecord) { ... }` helper that wraps a block in `ActiveRecord::Base.transaction` and rolls back when the yielded result is a failure.
117
+
118
+ ## [4.1.1] - 2020-10-15
119
+ ### Fixed
120
+ - Fix `Micro::Case#inspect` when the class declares an inner flow — recursion is now guarded with a thread-local key so nested inspections no longer loop.
121
+
122
+ ## [4.1.0] - 2020-10-14
123
+ ### Added
124
+ - Allow calling a use case or flow inside another use case via the private `call(use_case, defaults = {})` helper, automatically forwarding attributes/accessible attributes.
125
+ - Allow invoking a use case or flow with a block (`MyCase.call(...) do |result| result.success { ... }; result.failure { ... }; end`) backed by a new `Micro::Case::Result::Wrapper` (with `success`, `failure`, and `unknown` handlers).
126
+ - `Micro::Cases.map(...)` / `Micro::Cases::Map` to fan out the same input across multiple use cases and collect their results.
127
+ - Allow dependency injection in both static (`flow A, [B, dep: ...], C`) and inner-flow definitions via `[UseCase, defaults_hash]` tuples.
128
+ - `Micro.case?(arg)` predicate (in addition to the existing `Micro.case_or_flow?`).
129
+ - Track an "unknown" result state and expose `Result#unknown?` plus the `on_unknown` hook so unhandled success/failure types can be caught.
130
+ - `Micro::Cases::Error` used for invalid use-case errors raised by flows and `Cases::Map`.
131
+ - New internals: `Micro::Cases::Utils` (`MapUseCases`, `IsAValidUseCase`, …) and a `Micro::Case::Utils::Hashes.stringify_keys` helper.
132
+
133
+ ### Changed
134
+ - `Micro::Case.new` is now a private class method — use `.call` / `.__new__` (internal) instead of constructing instances directly.
135
+ - Drop the `u-attributes` `:initialize` and `:diff` extensions; `Micro::Case` now `include Micro::Attributes` directly.
136
+ - Refine `Result#inspect` to omit the `transitions=` segment when transitions are disabled.
137
+
138
+ ### Fixed
139
+ - Fix inner flows declared with an array argument.
140
+
141
+ ## [4.0.0] - 2020-08-20
142
+ Major rewrite. The headline shifts:
143
+ - `Micro::Case::Result` now starts in an "unknown" state and only transitions to handled once `on_success`/`on_failure` matches, unlocking the upcoming `on_unknown` workflow.
144
+ - The gem now requires the brand-new `u-attributes ~> 2.0` runtime, which changes how attribute inheritance works for `Micro::Case` subclasses.
145
+ - The `Micro::Case::Result` transitions mapper now always defaults to `Transitions::MapEverything`.
146
+
147
+ ### Added
148
+ - `Micro::Case::Result#to_sym` returning `:success` or `:failure`.
149
+
150
+ ### Changed
151
+ - **BREAKING:** Bump runtime dependency `u-attributes` from `~> 1.1` to `~> 2.0`; switch the internal include from `Micro::Attributes.without(:strict_initialize)` to `Micro::Attributes.with(:initialize, :diff)` and update the inheritance hook accordingly.
152
+ - Refactor `Micro::Case::Result` construction so `transitions_mapper` defaults to `Transitions::MapEverything` directly and `MapEverything` uses `result.to_sym` instead of an intermediate local.
153
+ - Update gem summary/description to "Represent use cases in a simple and powerful way while writing modular, expressive and sequentially logical code."
154
+
155
+ ### Removed
156
+ - Remove the `--pre` flag references from the docs/install instructions now that 4.x ships as a stable release.
157
+
158
+ ## [3.1.0] - 2020-08-17
159
+ ### Added
160
+ - `Micro::Case#apply` as a private alias for `#method` to make internal step composition more idiomatic.
161
+ - `Micro::Case::Result::Transitions` extracted as a dedicated class to model the sequence of steps executed by a use case / flow.
162
+
163
+ ### Changed
164
+ - Freeze `Micro::Case::Result#data` so the accumulated payload cannot be mutated by callers.
165
+ - Internal refactor of `Micro::Case::Result` and minor README/translation polish.
166
+
167
+ ### Fixed
168
+ - Improve handling and error feedback when `Micro::Case::Result#then` is invoked with an invalid argument.
169
+
170
+ ## [3.0.0] - 2020-08-14
171
+ Major rewrite consolidating nine release candidates. Highlights:
172
+
173
+ ### Added
174
+ - New flow builders `Micro::Cases.flow(...)` and `Micro::Cases.safe_flow(...)` replacing the previous `Micro::Case::Flow()` / `Micro::Case::Safe::Flow()` constructors.
175
+ - `Micro::Case::Result#data` holding the accumulated step output, plus `Result#[]`, `Result#values_at`, `Result#key?`, `Result#value?` and `Result#slice` for ergonomic data access.
176
+ - `Micro::Case::Result#transitions` exposing the ordered history of steps executed during a use case / flow.
177
+ - `Micro::Case.config` for global configuration (e.g. enabling/disabling transitions tracking, ActiveModel validation).
178
+ - `Micro::Case.then` and `Micro::Cases::Flow#then` so use cases and flows can be chained.
179
+ - `Micro::Case::Result#then` / `Result#|` accept a `Micro::Case` class, a flow, a method instance or a block, and accumulate data across the chain.
180
+ - Declare a use case's steps by referencing its own private methods.
181
+ - Top-level introspection helpers `Micro.case?` and `Micro.case_or_flow?`.
182
+ - Success results expose the use case instance that produced them.
183
+
184
+ ### Changed
185
+ - **BREAKING:** `Success`/`Failure` results are now declared via the `result:` keyword argument instead of a block (e.g. `Success(result: { ... })`).
186
+ - **BREAKING:** Result payloads must be a `Hash`; the result `type` must be a `Symbol`; failure results coming from an `Exception` are normalized accordingly. Defining an invalid success/failure now raises an explicit error.
187
+ - **BREAKING:** Static use case methods renamed to the new convention (e.g. `Micro::Case.call!`, `.__new!`) and inner flow constant renamed from `Flow_Step` to `Self`.
188
+ - Bumped the `kind` gem to the next major version.
189
+ - Only two ways to define a flow are now supported; the legacy `Flow::Reducer` was removed.
190
+
191
+ ### Removed
192
+ - **BREAKING:** `Micro::Case#call` instance method — use cases are invoked via the class-level API.
193
+ - **BREAKING:** `Micro::Case::Flow()` and `Micro::Case::Safe::Flow()` constructors (replaced by `Micro::Cases.flow` / `Micro::Cases.safe_flow`).
194
+ - The deprecated `u-case/with_validation` shim file.
195
+
196
+ ### Fixed
197
+ - Internal steps and flow execution behave correctly when result transitions tracking is disabled.
198
+ - Internal steps that receive a method instance now use keyword arguments (`**`) consistently.
199
+
200
+ ## [3.0.0.rc9] - 2020-08-14
201
+ ### Changed
202
+ - Internal steps that receive a method instance now use keyword arguments for parameter passing.
203
+
204
+ ## [3.0.0.rc8] - 2020-08-14
205
+ ### Fixed
206
+ - Flow execution when result transitions are disabled.
207
+ - Internal steps that receive a method instance now use the double-splat operator.
208
+
209
+ ## [3.0.0.rc7] - 2020-08-13
210
+ ### Fixed
211
+ - Internal steps when result transitions are disabled.
212
+
213
+ ## [3.0.0.rc6] - 2020-08-12
214
+ ### Added
215
+ - `Micro::Case::Result#then` / `Result#|` accept a method instance, in addition to a block or use case.
216
+
217
+ ### Changed
218
+ - `Micro::Case::Result#then` / `Result#|` now accumulate data across the chain.
219
+ - Default branch references migrated from `master` to `main`.
220
+
221
+ ## [3.0.0.rc5] - 2020-08-12
222
+ ### Added
223
+ - `Micro::Case.then` and `Micro::Cases::Flow#then` so use cases and flows can be chained.
224
+ - `Micro::Case::Result#key?`, `Result#value?` and `Result#slice` for ergonomic data access.
225
+
226
+ ### Changed
227
+ - Renamed inner flow constant `Flow_Step` to `Self`.
228
+ - Refactored `Micro::Cases::Flow` input handling.
229
+ - pt-BR README translation introduced; READMEs, logo and assets refreshed.
230
+
231
+ ## [3.0.0.rc4] - 2020-08-02
232
+ ### Added
233
+ - Declare use case steps by referencing private methods of the use case.
234
+ - Top-level introspection helpers `Micro.case?` and `Micro.case_or_flow?`.
235
+
236
+ ### Changed
237
+ - **BREAKING:** Static public methods of `Micro::Case` renamed to the new convention.
238
+ - Validate the output of lambdas passed to `Micro::Case::Result#then` / `Result#|`.
239
+ - Result transitions now also include the steps coming from internal step methods.
240
+
241
+ ### Removed
242
+ - **BREAKING:** `Micro::Case#call` instance method.
243
+
244
+ ## [3.0.0.rc3] - 2020-07-29
245
+ ### Added
246
+ - `Micro::Case.config` for global configuration of the library (e.g. transitions tracking, ActiveModel validation).
247
+ - Success results now expose the use case instance that produced them.
248
+
249
+ ## [3.0.0.rc2] - 2020-07-28
250
+ ### Changed
251
+ - Prepare for the next major version of the `kind` gem.
252
+ - Refactor `Micro::Case::Error::InvalidResult` and improve the error message raised when a use case returns the wrong result type.
253
+
254
+ ### Removed
255
+ - The deprecated `lib/u-case/with_validation.rb` shim.
256
+
257
+ ## [3.0.0.rc1] - 2020-07-21
258
+ ### Added
259
+ - New flow builders `Micro::Cases.flow(...)` / `Micro::Cases.safe_flow(...)`.
260
+ - `Micro::Case::Result#data` exposing the accumulated payload, plus `Result#[]` and `Result#values_at`.
261
+ - `Micro::Case::Result#transitions` exposing the ordered history of executed steps.
262
+ - Result payloads can now be initialized from a `Hash`, `Symbol` or `Exception`.
263
+
264
+ ### Changed
265
+ - **BREAKING:** `Success`/`Failure` results are now declared via the `result:` keyword argument instead of a block.
266
+ - **BREAKING:** `Micro::Case::Result#then` now yields the result itself and returns the block's value.
267
+ - **BREAKING:** Only two ways to define a flow are supported; the legacy `Flow::Reducer` was removed.
268
+ - Defining an invalid success/failure result now raises an explicit error.
269
+
270
+ ### Removed
271
+ - **BREAKING:** `Micro::Case::Flow()` and `Micro::Case::Safe::Flow()` constructors — use `Micro::Cases.flow` / `Micro::Cases.safe_flow` instead.
272
+
273
+ ## [2.6.0] - 2020-07-07
274
+ ### Added
275
+ - New behavior for `Micro::Case::Result#then` to chain another use case from a result.
276
+
277
+ ### Fixed
278
+ - `Micro::Case::Result#transitions` no longer produces incorrect/duplicated entries when chaining via `#then`.
279
+
280
+ ## [2.5.0] - 2020-06-26
281
+ ### Added
282
+ - `Micro::Case::Result#on_exception` hook to handle exceptions raised inside a use case.
283
+
284
+ ### Changed
285
+ - Forbid inheritance from a use case that defines an inner flow (raises an explicit error instead of silently misbehaving).
286
+
287
+ ## [2.4.0] - 2020-06-26
288
+ ### Added
289
+ - New file `u-case/with_activemodel_validation` so projects can opt into the ActiveModel-backed validation flavor explicitly.
290
+ - `Micro::Case::Utils` helper module.
291
+ - `Kind.of.Micro::Case::Result` type checker (via the new `kind` runtime dependency).
292
+ - `Micro::Case::Result#transitions` exposing the step-by-step history of a flow, including `:accessible_attributes` for each step.
293
+ - `Micro::Case::Result.disable_transition_tracking` configuration to opt out of transition tracking.
294
+ - New built-in support for validations via `Kind::Validator` (alongside ActiveModel).
295
+ - The use case instance is now exposed on successful results.
296
+
297
+ ### Changed
298
+ - `kind` is now a runtime dependency (bumped to `~> 3.0`).
299
+ - `require "u-case/with_validation"` now also loads the ActiveModel-based validation layer for backward compatibility.
300
+
301
+ ## [2.3.1] - 2019-12-29
302
+ ### Fixed
303
+ - Use-case validation no longer breaks when the class also declares a flow.
304
+
305
+ ## [2.3.0] - 2019-12-17
306
+ ### Added
307
+ - `Micro::Case::Result#then` to pipe a successful result into another use case (or block).
308
+ - Clearer error messages raised by `Micro::Case` when misused.
309
+
310
+ ## [2.2.0] - 2019-12-12
311
+ ### Added
312
+ - The flow definition (`flow ...`) can now be declared independently of the attribute declarations, making class layout more flexible.
313
+
314
+ ## [2.1.1] - 2019-12-12
315
+ ### Fixed
316
+ - Flow execution when a participating use case declares validations.
317
+
318
+ ## [2.1.0] - 2019-12-12
319
+ ### Added
320
+ - A `Micro::Case` subclass can declare its own internal flow and include itself in that flow.
321
+
322
+ ### Deprecated
323
+ - The `Micro::Case::Flow` mixin — declare flows directly on the use case class instead.
324
+
325
+ ## [2.0.0] - 2019-11-19
326
+ First stable 2.0 release. Includes everything from the 2.0.0.pre series plus:
327
+
328
+ ### Added
329
+ - Per-class opt-out from the automatic validation step (`disable_auto_validation`).
330
+
331
+ ## [2.0.0.pre.4] - 2019-11-19
332
+ ### Changed
333
+ - A flow now accumulates the success results of each step and feeds the merged data as input into the next use case.
334
+ - Renamed the custom test assertion helpers for `Micro::Case::Result` objects (final naming).
335
+
336
+ ## [2.0.0.pre.3] - 2019-11-14
337
+ ### Fixed
338
+ - `Micro::Case::Safe.Flow()` definition.
339
+ - `on_failure` without an explicit type now exposes a `Micro::Case::Result::Data` value instead of leaking internals.
340
+
341
+ ## [2.0.0.pre.2] - 2019-11-13
342
+ ### Changed
343
+ - New API for defining flows that operate over collections.
344
+
345
+ ## [2.0.0.pre] - 2019-11-12
346
+ ### Changed
347
+ - **BREAKING:** `Micro::Case::Base` was merged into `Micro::Case` — inherit from `Micro::Case` directly.
348
+ - **BREAKING:** `Micro::Case::Flow::Safe` was renamed to `Micro::Case::Safe::Flow`.
349
+ - Filenames using the old `pipeline` terminology were renamed to `flow`.
350
+
351
+ ### Added
352
+ - New custom Minitest assertions for `Micro::Case::Result` (`assert_success_result`, `assert_failure_result`, `assert_result`).
353
+
354
+ ## [1.1.0] - 2019-10-04
355
+ ### Changed
356
+ - Validation failure results now expose their errors as a `Hash` for consistent destructuring.
357
+
358
+ ## [1.0.0] - 2019-09-15
359
+ First release under the `u-case` name (renamed from `u-service`).
360
+
361
+ ### Changed
362
+ - **BREAKING:** Gem renamed from `u-service` to `u-case`.
363
+ - **BREAKING:** `Micro::Service` namespace renamed to `Micro::Case` — update all references (`Micro::Service::Base` → `Micro::Case::Base`, `Micro::Service::Strict` → `Micro::Case::Strict`, etc.).
364
+ - **BREAKING:** The "pipeline" concept was renamed to "flow" throughout the public API (`Micro::Service::Pipeline` → `Micro::Case::Flow`).
365
+
366
+ ---
367
+
368
+ ## Pre-rename history (published as `u-service`)
369
+
370
+ ## [u-service 1.0.0] - 2019-08-25
371
+ ### Added
372
+ - `Micro::Service::Safe` and `Micro::Service::Strict::Safe`: service variants that rescue exceptions and return them as failure results.
373
+ - Safe pipelines that intercept exceptions raised inside services; the failing service instance is exposed on the resulting failure.
374
+ - `Micro::Service::Error` module gathering all gem-specific exceptions in one namespace.
375
+ - `to_proc` on services and pipelines, enabling use with iterators like `map(&MyService)`.
376
+ - `:exception` is returned as the result type whenever a failure value is an `Exception`.
377
+ - When a failure is invoked with a `Symbol`, that symbol is used as both the result type and value.
378
+
379
+ ### Changed
380
+ - Any `ArgumentError` raised during service usage is now treated as a wrong-usage case and re-raised (even inside safe pipelines), instead of being swallowed as a failure.
381
+ - Pipeline reducers extracted into their own files; safe-pipeline reducer reworked for clarity.
382
+ - Default failure type for safe services improved so rescued exceptions produce a consistent `:exception` type.
383
+
384
+ ## [u-service 0.14.0] - 2019-08-19
385
+ ### Added
386
+ - Failure results now expose the service instance that produced them (accessible from the result), making it easier to identify which step in a pipeline failed.
387
+
388
+ ### Changed
389
+ - Improved error messages when an invalid value is assigned as a result.
390
+
391
+ ## [u-service 0.13.1] - 2019-08-19
392
+ ### Changed
393
+ - Slimmed the published gem by excluding files unnecessary at runtime.
394
+
395
+ ## [u-service 0.13.0] - 2019-08-19
396
+ ### Added
397
+ - `require 'u-service/with_validation'` shortcut to enable the ActiveModel-validation mode.
398
+ - Default result types: `:ok` for success and `:error` for failure when none is provided.
399
+ - New `:validation_error` result type returned automatically when a validated service is invalid.
400
+
401
+ ### Changed
402
+ - Result `type` is always coerced to a `Symbol`.
403
+ - The validation mode now modifies the base class on load rather than exposing separate `Validation` classes, simplifying the public API.
404
+
405
+ ### Removed
406
+ - The internal `Validation` classes layer (superseded by the base-class extension above).
407
+
408
+ ## [u-service 0.12.0] - 2019-08-14
409
+ ### Changed
410
+ - Reduced object allocation while processing a pipeline, improving throughput.
411
+
412
+ ## [u-service 0.11.0] - 2019-08-13
413
+ ### Added
414
+ - Pipelines defined as classes are now validated at definition time, surfacing configuration mistakes earlier.
415
+ - Pipelines can be composed of other `Micro::Service` abstractions (services and pipelines used interchangeably as steps).
416
+
417
+ ## [u-service 0.10.0] - 2019-08-10
418
+ ### Added
419
+ - Composition operator for building a pipeline from services and/or other pipelines (e.g. `ServiceA >> ServiceB`).
420
+
421
+ ## [u-service 0.9.0] - 2019-08-09
422
+ ### Added
423
+ - `Micro::Service::Result::Success` and `Micro::Service::Result::Failure` subclasses, plus a `Result::Helpers` module — making it easier to pattern-match or branch on result kind.
424
+
425
+ ## [u-service 0.8.0] - 2019-08-08
426
+ ### Added
427
+ - Alternative class-level DSL for declaring pipelines inside a class (in addition to `Micro::Service::Pipeline[...]`).
428
+
429
+ ## [u-service 0.7.0] - 2019-08-06
430
+ ### Changed
431
+ - Optimized `Micro::Service::Pipeline` execution.
432
+
433
+ ## [u-service 0.6.0] - 2019-08-06
434
+ ### Added
435
+ - `Micro::Service::WithValidation`, integrating ActiveModel validations into services so invalid input short-circuits with a failure.
436
+ - CI matrix expanded to run against multiple ActiveModel versions.
437
+
438
+ ## [u-service 0.5.0] - 2019-08-06
439
+ ### Added
440
+ - Pipelines can be called with an existing `Result` as their starting input, enabling chaining across pipelines.
441
+
442
+ ### Changed
443
+ - Renamed `Micro::Service::Strict::Base` to `Micro::Service::Strict`.
444
+
445
+ ### Removed
446
+ - `Micro::Service::Strict::Base` (replaced by `Micro::Service::Strict`).
447
+
448
+ ## [u-service 0.4.0] - 2019-08-05
449
+ ### Added
450
+ - `Micro::Service::Result#type` is now validated (must be a non-blank symbol/string).
451
+
452
+ ### Changed
453
+ - **BREAKING:** New positional/block API for `Success` and `Failure` helpers and factories: pass either a value directly, or a type as the argument and the value via block (e.g. `Failure(:invalid) { reason }`). The old `value:` / `type:` keyword combination no longer applies.
454
+
455
+ ## [u-service 0.3.0] - 2019-08-05
456
+ ### Added
457
+ - `Micro::Service::Pipeline` — compose multiple services into a single callable pipeline via `Micro::Service::Pipeline[ServiceA, ServiceB, ...]`.
458
+ - Argument validation for `Micro::Service::Pipeline[]` to catch bad pipeline definitions up front.
459
+
460
+ ## [u-service 0.2.0] - 2019-08-05
461
+ ### Added
462
+ - `Micro::Service::Strict::Base` — a strict variant that enforces that all declared attributes are provided.
463
+
464
+ ## [u-service 0.1.0] - 2019-08-05
465
+ ### Added
466
+ - Initial release of `u-service`.
467
+ - `Micro::Service::Base`: define services with attribute-based input and a `call!` method.
468
+ - `Micro::Service::Result` with `Success`/`Failure` factories and helper methods for returning typed results from services.
469
+ - Runtime dependency on `u-attributes` for service input declaration.
470
+
471
+ [5.4.0]: https://github.com/serradura/u-case/compare/v5.3.1...v5.4.0
472
+ [5.3.1]: https://github.com/serradura/u-case/compare/v5.3.0...v5.3.1
473
+ [5.3.0]: https://github.com/serradura/u-case/compare/v5.2.1...v5.3.0
474
+ [5.2.1]: https://github.com/serradura/u-case/compare/v5.2.0...v5.2.1
475
+ [5.2.0]: https://github.com/serradura/u-case/compare/v5.1.0...v5.2.0
476
+ [5.1.0]: https://github.com/serradura/u-case/compare/v5.0.0...v5.1.0
477
+ [5.0.0]: https://github.com/serradura/u-case/compare/v4.5.2...v5.0.0
478
+ [4.5.2]: https://github.com/serradura/u-case/compare/v4.5.1...v4.5.2
479
+ [4.5.1]: https://github.com/serradura/u-case/compare/v4.5.0...v4.5.1
480
+ [4.5.0]: https://github.com/serradura/u-case/compare/v4.4.0...v4.5.0
481
+ [4.4.0]: https://github.com/serradura/u-case/compare/v4.3.0...v4.4.0
482
+ [4.3.0]: https://github.com/serradura/u-case/compare/v4.2.2...v4.3.0
483
+ [4.2.2]: https://github.com/serradura/u-case/compare/v4.2.1...v4.2.2
484
+ [4.2.1]: https://github.com/serradura/u-case/compare/v4.2.0...v4.2.1
485
+ [4.2.0]: https://github.com/serradura/u-case/compare/v4.1.1...v4.2.0
486
+ [4.1.1]: https://github.com/serradura/u-case/compare/v4.1.0...v4.1.1
487
+ [4.1.0]: https://github.com/serradura/u-case/compare/v4.0.0...v4.1.0
488
+ [4.0.0]: https://github.com/serradura/u-case/compare/v3.1.0...v4.0.0
489
+ [3.1.0]: https://github.com/serradura/u-case/compare/v3.0.0...v3.1.0
490
+ [3.0.0]: https://github.com/serradura/u-case/compare/v3.0.0.rc9...v3.0.0
491
+ [3.0.0.rc9]: https://github.com/serradura/u-case/compare/v3.0.0.rc8...v3.0.0.rc9
492
+ [3.0.0.rc8]: https://github.com/serradura/u-case/compare/v3.0.0.rc7...v3.0.0.rc8
493
+ [3.0.0.rc7]: https://github.com/serradura/u-case/compare/v3.0.0.rc6...v3.0.0.rc7
494
+ [3.0.0.rc6]: https://github.com/serradura/u-case/compare/v3.0.0.rc5...v3.0.0.rc6
495
+ [3.0.0.rc5]: https://github.com/serradura/u-case/compare/v3.0.0.rc4...v3.0.0.rc5
496
+ [3.0.0.rc4]: https://github.com/serradura/u-case/compare/v3.0.0.rc3...v3.0.0.rc4
497
+ [3.0.0.rc3]: https://github.com/serradura/u-case/compare/v3.0.0.rc2...v3.0.0.rc3
498
+ [3.0.0.rc2]: https://github.com/serradura/u-case/compare/v3.0.0.rc1...v3.0.0.rc2
499
+ [3.0.0.rc1]: https://github.com/serradura/u-case/compare/v2.6.0...v3.0.0.rc1
500
+ [2.6.0]: https://github.com/serradura/u-case/compare/v2.5.0...v2.6.0
501
+ [2.5.0]: https://github.com/serradura/u-case/compare/v2.4.0...v2.5.0
502
+ [2.4.0]: https://github.com/serradura/u-case/compare/v2.3.1...v2.4.0
503
+ [2.3.1]: https://github.com/serradura/u-case/compare/v2.3.0...v2.3.1
504
+ [2.3.0]: https://github.com/serradura/u-case/compare/v2.2.0...v2.3.0
505
+ [2.2.0]: https://github.com/serradura/u-case/compare/v2.1.1...v2.2.0
506
+ [2.1.1]: https://github.com/serradura/u-case/compare/v2.1.0...v2.1.1
507
+ [2.1.0]: https://github.com/serradura/u-case/compare/v2.0.0...v2.1.0
508
+ [2.0.0]: https://github.com/serradura/u-case/compare/v2.0.0.pre.4...v2.0.0
509
+ [2.0.0.pre.4]: https://github.com/serradura/u-case/compare/v2.0.0.pre.3...v2.0.0.pre.4
510
+ [2.0.0.pre.3]: https://github.com/serradura/u-case/compare/v2.0.0.pre.2...v2.0.0.pre.3
511
+ [2.0.0.pre.2]: https://github.com/serradura/u-case/compare/v2.0.0.pre...v2.0.0.pre.2
512
+ [2.0.0.pre]: https://github.com/serradura/u-case/compare/v1.1.0...v2.0.0.pre
513
+ [1.1.0]: https://github.com/serradura/u-case/compare/v1.0.0...v1.1.0
514
+ [1.0.0]: https://github.com/serradura/u-case/compare/u-service-v1.0.0...v1.0.0
515
+ [u-service 1.0.0]: https://github.com/serradura/u-case/compare/u-service-v0.14.0...u-service-v1.0.0
516
+ [u-service 0.14.0]: https://github.com/serradura/u-case/compare/u-service-v0.13.1...u-service-v0.14.0
517
+ [u-service 0.13.1]: https://github.com/serradura/u-case/compare/u-service-v0.13.0...u-service-v0.13.1
518
+ [u-service 0.13.0]: https://github.com/serradura/u-case/compare/u-service-v0.12.0...u-service-v0.13.0
519
+ [u-service 0.12.0]: https://github.com/serradura/u-case/compare/u-service-v0.11.0...u-service-v0.12.0
520
+ [u-service 0.11.0]: https://github.com/serradura/u-case/compare/u-service-v0.10.0...u-service-v0.11.0
521
+ [u-service 0.10.0]: https://github.com/serradura/u-case/compare/u-service-v0.9.0...u-service-v0.10.0
522
+ [u-service 0.9.0]: https://github.com/serradura/u-case/compare/u-service-v0.8.0...u-service-v0.9.0
523
+ [u-service 0.8.0]: https://github.com/serradura/u-case/compare/u-service-v0.7.0...u-service-v0.8.0
524
+ [u-service 0.7.0]: https://github.com/serradura/u-case/compare/u-service-v0.6.0...u-service-v0.7.0
525
+ [u-service 0.6.0]: https://github.com/serradura/u-case/compare/u-service-v0.5.0...u-service-v0.6.0
526
+ [u-service 0.5.0]: https://github.com/serradura/u-case/compare/u-service-v0.4.0...u-service-v0.5.0
527
+ [u-service 0.4.0]: https://github.com/serradura/u-case/compare/u-service-v0.3.0...u-service-v0.4.0
528
+ [u-service 0.3.0]: https://github.com/serradura/u-case/compare/u-service-v0.2.0...u-service-v0.3.0
529
+ [u-service 0.2.0]: https://github.com/serradura/u-case/compare/u-service-v0.1.0...u-service-v0.2.0
530
+ [u-service 0.1.0]: https://github.com/serradura/u-case/releases/tag/u-service-v0.1.0
data/CLAUDE.md ADDED
@@ -0,0 +1,149 @@
1
+ # CLAUDE.md
2
+
3
+ Notes for AI assistants working in `u-case`.
4
+
5
+ ## How to work in this repo
6
+
7
+ ### 1. Think before coding
8
+
9
+ **Don't assume. Don't hide confusion. Surface tradeoffs.**
10
+
11
+ - State assumptions explicitly. If uncertain, ask.
12
+ - If multiple interpretations exist, present them — don't pick silently.
13
+ - If a simpler approach exists, say so. Push back when warranted.
14
+ - If something is unclear, stop. Name what's confusing. Ask.
15
+
16
+ ### 2. Simplicity first
17
+
18
+ **Minimum code that solves the problem. Nothing speculative.**
19
+
20
+ - No features beyond what was asked.
21
+ - No abstractions for single-use code.
22
+ - No "flexibility" or "configurability" that wasn't requested.
23
+ - No error handling for impossible scenarios.
24
+ - If you write 200 lines and it could be 50, rewrite it.
25
+
26
+ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes,
27
+ simplify.
28
+
29
+ ### 3. Surgical changes
30
+
31
+ **Touch only what you must. Clean up only your own mess.**
32
+
33
+ - Don't "improve" adjacent code, comments, or formatting.
34
+ - Don't refactor things that aren't broken.
35
+ - Match existing style, even if you'd do it differently.
36
+ - If you notice unrelated dead code, mention it — don't delete it.
37
+ - Remove imports/variables/functions that _your_ changes orphaned. Don't
38
+ remove pre-existing dead code unless asked.
39
+
40
+ The test: every changed line should trace directly to the user's request.
41
+
42
+ ### 4. Goal-driven execution
43
+
44
+ **Define success criteria. Loop until verified.**
45
+
46
+ Turn vague tasks into verifiable goals:
47
+
48
+ - "Add validation" → "Write tests for invalid inputs, then make them pass"
49
+ - "Fix the bug" → "Write a test that reproduces it, then make it pass"
50
+ - "Refactor X" → "Ensure tests pass before and after"
51
+
52
+ For multi-step work, state a brief plan with a verification check per step.
53
+
54
+ ---
55
+
56
+ ## What this is
57
+
58
+ `u-case` is a Ruby gem (originally published as `u-service`) for representing
59
+ business use cases as small, composable objects with typed `Success`/`Failure`
60
+ results. Entry points live under `lib/micro/case` (`Micro::Case`,
61
+ `Micro::Case::Safe`, `Micro::Case::Result`, `Micro::Cases.flow`, etc.).
62
+ Behavior changes — especially anything that affects the public API or the
63
+ supported `ruby` / `activemodel` / `u-attributes` matrix — are highly visible
64
+ to downstream users.
65
+
66
+ ## Running tests
67
+
68
+ ```bash
69
+ bundle exec rake test # default suite, current bundle
70
+ bundle exec appraisal <name> rake test # one Rails appraisal (see Appraisals)
71
+ bundle exec rake matrix # full local matrix for the active Ruby
72
+ ```
73
+
74
+ `bin/setup` re-installs and refreshes appraisals. `bin/matrix` reinstalls then
75
+ runs `rake matrix`. CI runs the matrix across the full Ruby × Rails grid plus
76
+ the `ENABLE_TRANSITIONS=true|false` axis. Tests are the success criterion for
77
+ any behavior change — write or update a test first, then make it pass
78
+ (rule 4).
79
+
80
+ ## CHANGELOG and READMEs are part of every change
81
+
82
+ Both files are user-facing — keep them in sync with the code:
83
+
84
+ - **`CHANGELOG.md`**: follows [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/).
85
+ Every user-visible change (new API, behavior change, breaking change, dep
86
+ bump that shifts the supported matrix, security fix) gets a bullet under
87
+ the appropriate section (`Added` / `Changed` / `Deprecated` / `Removed` /
88
+ `Fixed` / `Security`). Pure README/CI/internal-refactor changes generally
89
+ don't need an entry.
90
+ - **`README.md` and `README.pt-BR.md`**: the **Documentation** table and the
91
+ **Compatibility** table at the top reference the latest released version
92
+ and its dependency bounds. Update both files together — they are
93
+ translations of each other and must stay in lockstep. If you change a
94
+ documented API, update both READMEs in the same commit.
95
+
96
+ ## Internal argument checks live in `Micro::Case::Check`
97
+
98
+ Every internal argument/contract check that runs inside the gem (type
99
+ guards, "is this a `Micro::Case`?", "is this a `Symbol`?", "are these
100
+ flow args valid?", etc.) lives in `lib/micro/case/check.rb`, split across
101
+ two modules with **identical method signatures**:
102
+
103
+ - `Micro::Case::Check::Enabled` — the default; raises the curated
104
+ `Micro::Case::Error::*` exceptions.
105
+ - `Micro::Case::Check::Disabled` — no-ops (the matching method just
106
+ `return`s; passthrough methods return their input unchanged).
107
+
108
+ The active one is referenced as `Micro::Case.check`, swapped by
109
+ `config.disable_runtime_checks = true/false` (see PR #145 / issue #45).
110
+
111
+ ### When you add a new internal check, you must:
112
+
113
+ 1. **Add the method to BOTH modules.** Keep the signature identical.
114
+ The `Enabled` side does the real work; the `Disabled` side is a
115
+ no-op (or passthrough for `hash!`-style coercions).
116
+ 2. **Route the call site through `Micro::Case.check.<method>!(...)`.**
117
+ Don't `raise ... unless ...` inline — that bypasses the toggle and
118
+ leaks the check into the disabled-path performance budget.
119
+ 3. **Cover both modes in a test.** Mirror the pattern in
120
+ `test/micro/case/disable_runtime_checks_test.rb`: one test that the
121
+ `Enabled` side raises, one that the `Disabled` side does not.
122
+ 4. **Avoid extra allocation on the call site.** If the curated
123
+ exception needs dynamic params (a class name, a context string),
124
+ pass the raw strings/values into the check method and construct the
125
+ exception inside `Enabled` (only on the raise path). Don't build the
126
+ exception before calling — that defeats the perf rationale of the
127
+ `Disabled` side.
128
+
129
+ This is the only place where new gem-internal checks belong. Inline
130
+ `raise … unless …` inside the runtime call path is a regression of
131
+ this design — flag it during review and move the check into
132
+ `Micro::Case::Check`.
133
+
134
+ ## Bumping the version
135
+
136
+ 1. Edit `lib/micro/case/version.rb` — change `Micro::Case::VERSION`. Follow
137
+ [SemVer](https://semver.org/): patch for fixes, minor for additive
138
+ user-visible changes, major for breaking changes.
139
+ 2. Add a new top entry in `CHANGELOG.md` (`## [X.Y.Z] - YYYY-MM-DD`) and a
140
+ matching compare link at the bottom (`[X.Y.Z]: …/compare/vPREV...vX.Y.Z`).
141
+ 3. Update both READMEs:
142
+ - **Documentation** table → bump the `v5.x` (or current major) row's
143
+ version label.
144
+ - **Compatibility** table → if dependency bounds changed, add a new row;
145
+ otherwise bump the existing row's version label.
146
+ 4. If `Gemfile`/`u-case.gemspec` dependency bounds moved, double-check the
147
+ Compatibility table and `Appraisals` reflect the new bounds.
148
+
149
+ Don't tag, push, or `gem release` — humans do that.
data/README.md CHANGED
@@ -27,7 +27,7 @@ The main project goals are:
27
27
  Version | Documentation
28
28
  --------- | -------------
29
29
  unreleased| https://github.com/serradura/u-case/blob/main/README.md
30
- 5.2.1 | https://github.com/serradura/u-case/blob/v5.x/README.md
30
+ 5.4.0 | https://github.com/serradura/u-case/blob/v5.x/README.md
31
31
  4.5.1 | https://github.com/serradura/u-case/blob/v4.x/README.md
32
32
 
33
33
  > **Note:** Você entende português? 🇧🇷&nbsp;🇵🇹 Verifique o [README traduzido em pt-BR](https://github.com/serradura/u-case/blob/main/README.pt-BR.md).
@@ -90,7 +90,7 @@ unreleased| https://github.com/serradura/u-case/blob/main/README.md
90
90
  | u-case | branch | ruby | activemodel | u-attributes |
91
91
  | ---------------- | ------ | -------- | -------------- | -------------- |
92
92
  | unreleased | main | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
93
- | 5.2.1 | v5.x | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
93
+ | 5.4.0 | v5.x | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
94
94
  | 5.1.0 | v5.x | >= 2.7 | >= 6.0 | >= 2.7, < 4.0 |
95
95
  | 4.5.1 | v4.x | >= 2.2.0 | >= 3.2, <= 8.1 | >= 2.7, < 3.0 |
96
96
 
@@ -1256,9 +1256,22 @@ Micro::Case.config do |config|
1256
1256
  # - Calling `Micro::Cases.safe_flow(...)`
1257
1257
  # - Calling `Micro::Case::Result#on_exception`
1258
1258
  config.disable_safe_features = false
1259
+
1260
+ # Use to skip the gem's internal argument/contract checks (e.g., "is this a
1261
+ # Micro::Case?", "is the result type a Symbol?", "is the use case a kind of
1262
+ # Micro::Case?"). Set to `true` in production for a small performance boost
1263
+ # once your code paths are exercised by your test suite. The trade-off is that
1264
+ # incorrect usage will surface as confusing downstream errors instead of the
1265
+ # gem's curated ones (e.g. `Micro::Case::Error::InvalidUseCase`).
1266
+ config.disable_runtime_checks = false
1259
1267
  end
1260
1268
  ```
1261
1269
 
1270
+ All checks are consolidated in `Micro::Case::Check::Enabled` (the default).
1271
+ Toggling `disable_runtime_checks = true` swaps `Micro::Case.check` to
1272
+ `Micro::Case::Check::Disabled` — a module with the same signature whose
1273
+ methods are no-ops — so the validations themselves are not run on each call.
1274
+
1262
1275
  [⬆️ Back to Top](#table-of-contents-)
1263
1276
 
1264
1277
  ## Benchmarks
data/README.pt-BR.md CHANGED
@@ -27,7 +27,7 @@ Principais objetivos deste projeto:
27
27
  Versão | Documentação
28
28
  --------- | -------------
29
29
  unreleased| https://github.com/serradura/u-case/blob/main/README.md
30
- 5.2.1 | https://github.com/serradura/u-case/blob/v5.x/README.md
30
+ 5.4.0 | https://github.com/serradura/u-case/blob/v5.x/README.md
31
31
  4.5.1 | https://github.com/serradura/u-case/blob/v4.x/README.md
32
32
 
33
33
  ## Índice <!-- omit in toc -->
@@ -88,7 +88,7 @@ unreleased| https://github.com/serradura/u-case/blob/main/README.md
88
88
  | u-case | branch | ruby | activemodel | u-attributes |
89
89
  | ---------------- | ------ | -------- | -------------- | -------------- |
90
90
  | unreleased | main | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
91
- | 5.2.1 | v5.x | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
91
+ | 5.4.0 | v5.x | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
92
92
  | 5.1.0 | v5.x | >= 2.7 | >= 6.0 | >= 2.7, < 4.0 |
93
93
  | 4.5.1 | v4.x | >= 2.2.0 | >= 3.2, <= 8.1 | >= 2.7, < 3.0 |
94
94
 
@@ -1257,9 +1257,24 @@ Micro::Case.config do |config|
1257
1257
  # - Chamar `Micro::Cases.safe_flow(...)`
1258
1258
  # - Chamar `Micro::Case::Result#on_exception`
1259
1259
  config.disable_safe_features = false
1260
+
1261
+ # Use para pular as verificações internas de argumento/contrato da gem (por
1262
+ # exemplo, "isto é um Micro::Case?", "o tipo do resultado é um Symbol?",
1263
+ # "o use case é um tipo de Micro::Case?"). Defina `true` em produção para
1264
+ # um pequeno ganho de performance depois que seus caminhos de código já
1265
+ # estiverem cobertos pela sua suíte de testes. O custo é que usos
1266
+ # incorretos vão aparecer como erros confusos mais à frente, em vez dos
1267
+ # erros curados pela gem (ex.: `Micro::Case::Error::InvalidUseCase`).
1268
+ config.disable_runtime_checks = false
1260
1269
  end
1261
1270
  ```
1262
1271
 
1272
+ Todas as verificações estão consolidadas em `Micro::Case::Check::Enabled` (o
1273
+ padrão). Definir `disable_runtime_checks = true` troca `Micro::Case.check` por
1274
+ `Micro::Case::Check::Disabled` — um módulo com a mesma assinatura cujos
1275
+ métodos não fazem nada — de forma que as validações não são executadas a
1276
+ cada chamada.
1277
+
1263
1278
  [⬆️ Voltar para o índice](#índice-)
1264
1279
 
1265
1280
  ## Benchmarks
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ class Case
5
+ module Check
6
+ module Enabled
7
+ extend self
8
+
9
+ def use_case_or_flow!(arg)
10
+ raise Error::InvalidUseCase unless ::Micro.case_or_flow?(arg)
11
+ end
12
+
13
+ def micro_case_instance!(arg)
14
+ raise Error::InvalidUseCase unless arg.is_a?(::Micro::Case)
15
+ end
16
+
17
+ def result_instance!(arg)
18
+ raise Error::InvalidResultInstance unless arg.is_a?(::Micro::Case::Result)
19
+ end
20
+
21
+ def result_not_defined!(is_defined)
22
+ raise Error::ResultIsAlreadyDefined if is_defined
23
+ end
24
+
25
+ def result_type!(type)
26
+ raise Error::InvalidResultType unless type.is_a?(Symbol)
27
+ end
28
+
29
+ def result_data!(data, is_success, type, use_case)
30
+ raise Error::InvalidResult.new(is_success, type, use_case) unless data
31
+ end
32
+
33
+ def expected_result!(result, context)
34
+ return if result.is_a?(::Micro::Case::Result)
35
+
36
+ raise Error::UnexpectedResult.new(context)
37
+ end
38
+
39
+ def expected_self_result!(actual, expected, context)
40
+ return if actual.equal?(expected)
41
+
42
+ raise Error::UnexpectedResult.new(context)
43
+ end
44
+
45
+ def then_use_case_or_flow!(arg, owner_label)
46
+ return if ::Micro.case_or_flow?(arg)
47
+
48
+ raise Error::InvalidInvocationOfTheThenMethod.new(owner_label)
49
+ end
50
+
51
+ def flow_use_cases!(use_cases)
52
+ raise Cases::Error::InvalidUseCases if use_cases.none?(&::Micro::Cases::Flow::IsAValidUseCase)
53
+ end
54
+
55
+ def map_args!(args)
56
+ raise Cases::Error::InvalidUseCases unless ::Micro::Cases::Map.const_get(:HasValidArgs, false)[args]
57
+ end
58
+
59
+ def hash!(arg)
60
+ Kind::Hash[arg]
61
+ end
62
+ end
63
+
64
+ module Disabled
65
+ extend self
66
+
67
+ def use_case_or_flow!(_arg); end
68
+ def micro_case_instance!(_arg); end
69
+ def result_instance!(_arg); end
70
+ def result_not_defined!(_is_defined); end
71
+ def result_type!(_type); end
72
+ def result_data!(_data, _is_success, _type, _use_case); end
73
+ def expected_result!(_result, _context); end
74
+ def expected_self_result!(_actual, _expected, _context); end
75
+ def then_use_case_or_flow!(_arg, _owner_label); end
76
+ def flow_use_cases!(_use_cases); end
77
+ def map_args!(_args); end
78
+ def hash!(arg); arg; end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -23,6 +23,18 @@ module Micro
23
23
  @disable_safe_features = false
24
24
  end
25
25
 
26
+ def disable_runtime_checks=(value)
27
+ @disable_runtime_checks = Kind::Boolean[value]
28
+
29
+ ::Micro::Case.check = @disable_runtime_checks ? ::Micro::Case::Check::Disabled : ::Micro::Case::Check::Enabled
30
+ end
31
+
32
+ def disable_runtime_checks
33
+ return @disable_runtime_checks if defined?(@disable_runtime_checks)
34
+
35
+ @disable_runtime_checks = false
36
+ end
37
+
26
38
  def enable_activemodel_validation=(value)
27
39
  return unless Kind::Boolean[value]
28
40
 
@@ -174,14 +174,14 @@ module Micro
174
174
  end
175
175
 
176
176
  def __set__(is_success, data, type, use_case)
177
- raise Error::InvalidResultType unless type.is_a?(Symbol)
178
- raise Error::InvalidUseCase unless use_case.is_a?(::Micro::Case)
177
+ ::Micro::Case.check.result_type!(type)
178
+ ::Micro::Case.check.micro_case_instance!(use_case)
179
179
 
180
180
  @__success, @type, @use_case = is_success, type, use_case
181
181
 
182
182
  @data = FetchData.call(data).freeze
183
183
 
184
- raise Micro::Case::Error::InvalidResult.new(is_success, type, use_case) unless @data
184
+ ::Micro::Case.check.result_data!(@data, is_success, type, use_case)
185
185
 
186
186
  @__accumulated_data.merge!(@data)
187
187
 
@@ -227,7 +227,7 @@ module Micro
227
227
  use_case_method = self.use_case.method(use_case)
228
228
  __call_method(use_case_method, attributes)
229
229
  else
230
- raise INVALID_INVOCATION_OF_THE_THEN_METHOD unless ::Micro.case_or_flow?(use_case)
230
+ ::Micro::Case.check.then_use_case_or_flow!(use_case, 'Micro::Case::Result#')
231
231
 
232
232
  input = attributes.is_a?(Hash) ? self.data.merge(attributes) : self.data
233
233
 
@@ -244,9 +244,9 @@ module Micro
244
244
 
245
245
  result = fn.arity.zero? ? fn.call : fn.call(__fetch_accessible_attributes)
246
246
 
247
- return self if result === self
247
+ ::Micro::Case.check.expected_self_result!(result, self, "#{Result.name}##{expected}")
248
248
 
249
- raise Error::UnexpectedResult.new("#{Result.name}##{expected}")
249
+ self
250
250
  end
251
251
 
252
252
  def __call_method(methd, attributes = nil)
@@ -254,9 +254,9 @@ module Micro
254
254
 
255
255
  result = methd.arity.zero? ? methd.call : methd.call(**__fetch_accessible_attributes)
256
256
 
257
- return self if result === self
257
+ ::Micro::Case.check.expected_self_result!(result, self, "#{use_case.class.name}#method(:#{methd.name})")
258
258
 
259
- raise Error::UnexpectedResult.new("#{use_case.class.name}#method(:#{methd.name})")
259
+ self
260
260
  end
261
261
 
262
262
  def __success_type?(expected_type)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  class Case
5
- VERSION = '5.3.0'.freeze
5
+ VERSION = '5.4.0'.freeze
6
6
  end
7
7
  end
data/lib/micro/case.rb CHANGED
@@ -11,12 +11,18 @@ module Micro
11
11
  require 'micro/case/utils'
12
12
  require 'micro/case/error'
13
13
  require 'micro/case/result'
14
+ require 'micro/case/check'
14
15
  require 'micro/case/config'
15
16
  require 'micro/case/safe'
16
17
  require 'micro/case/strict'
17
18
 
18
19
  require 'micro/cases'
19
20
 
21
+ class << self
22
+ attr_accessor :check
23
+ end
24
+ self.check = Check::Enabled
25
+
20
26
  include Micro::Attributes
21
27
  include Micro::Attributes::Features::Accept
22
28
 
@@ -46,7 +52,7 @@ module Micro
46
52
  else
47
53
  return yield_self if !use_case && can_yield_self
48
54
 
49
- raise INVALID_INVOCATION_OF_THE_THEN_METHOD unless ::Micro.case_or_flow?(use_case)
55
+ ::Micro::Case.check.then_use_case_or_flow!(use_case, 'Micro::Case.')
50
56
 
51
57
  self.call.then(use_case)
52
58
  end
@@ -169,8 +175,8 @@ module Micro
169
175
  end
170
176
 
171
177
  def __set_result__(result)
172
- raise Error::InvalidResultInstance unless result.is_a?(Result)
173
- raise Error::ResultIsAlreadyDefined if defined?(@__result)
178
+ ::Micro::Case.check.result_instance!(result)
179
+ ::Micro::Case.check.result_not_defined!(defined?(@__result))
174
180
 
175
181
  @__result = result
176
182
 
@@ -180,7 +186,7 @@ module Micro
180
186
  private
181
187
 
182
188
  def call(use_case, defaults = Kind::Empty::HASH)
183
- raise Error::InvalidUseCase unless ::Micro.case_or_flow?(use_case)
189
+ ::Micro::Case.check.use_case_or_flow!(use_case)
184
190
 
185
191
  input =
186
192
  defaults.empty? ? attributes : attributes.merge(Utils::Hashes.stringify_keys(defaults))
@@ -211,9 +217,9 @@ module Micro
211
217
 
212
218
  result = call!
213
219
 
214
- return result if result.is_a?(Result)
220
+ ::Micro::Case.check.expected_result!(result, "#{self.class.name}#call!")
215
221
 
216
- raise Error::UnexpectedResult.new("#{self.class.name}#call!")
222
+ result
217
223
  end
218
224
 
219
225
  def __attributes_errors_present?
@@ -11,7 +11,7 @@ module Micro
11
11
  def self.build(args)
12
12
  use_cases = Utils.map_use_cases(args)
13
13
 
14
- raise Error::InvalidUseCases if use_cases.none?(&IsAValidUseCase)
14
+ ::Micro::Case.check.flow_use_cases!(use_cases)
15
15
 
16
16
  new(use_cases)
17
17
  end
@@ -63,7 +63,7 @@ module Micro
63
63
  else
64
64
  return yield_self if !use_case && can_yield_self
65
65
 
66
- raise_invalid_invocation_of_the_then_method unless ::Micro.case_or_flow?(use_case)
66
+ ::Micro::Case.check.then_use_case_or_flow!(use_case, "#{self.class.name}#")
67
67
 
68
68
  self.call.then(use_case)
69
69
  end
@@ -10,7 +10,7 @@ module Micro
10
10
  attr_reader :use_cases
11
11
 
12
12
  def self.build(args)
13
- raise Error::InvalidUseCases unless HasValidArgs[args]
13
+ ::Micro::Case.check.map_args!(args)
14
14
 
15
15
  new(args)
16
16
  end
@@ -30,7 +30,7 @@ module Micro
30
30
  end
31
31
 
32
32
  def call(arg = {})
33
- hash = Kind::Hash[arg]
33
+ hash = ::Micro::Case.check.hash!(arg)
34
34
 
35
35
  use_cases.map(&GetUseCaseResult[hash])
36
36
  end
data/u-case.gemspec CHANGED
@@ -16,6 +16,10 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
18
18
 
19
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
20
+ spec.metadata['source_code_uri'] = spec.homepage
21
+ spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
22
+
19
23
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
24
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|assets|benchmarks|comparisons|examples)/}) }
21
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-case
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.0
4
+ version: 5.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
@@ -104,6 +104,8 @@ files:
104
104
  - ".tool-versions"
105
105
  - ".vscode/settings.json"
106
106
  - Appraisals
107
+ - CHANGELOG.md
108
+ - CLAUDE.md
107
109
  - CODE_OF_CONDUCT.md
108
110
  - Gemfile
109
111
  - LICENSE.txt
@@ -116,6 +118,7 @@ files:
116
118
  - gemfiles/rails_8_1.gemfile
117
119
  - gemfiles/rails_edge.gemfile
118
120
  - lib/micro/case.rb
121
+ - lib/micro/case/check.rb
119
122
  - lib/micro/case/config.rb
120
123
  - lib/micro/case/error.rb
121
124
  - lib/micro/case/result.rb
@@ -138,7 +141,10 @@ files:
138
141
  homepage: https://github.com/serradura/u-case
139
142
  licenses:
140
143
  - MIT
141
- metadata: {}
144
+ metadata:
145
+ changelog_uri: https://github.com/serradura/u-case/blob/main/CHANGELOG.md
146
+ source_code_uri: https://github.com/serradura/u-case
147
+ bug_tracker_uri: https://github.com/serradura/u-case/issues
142
148
  rdoc_options: []
143
149
  require_paths:
144
150
  - lib