u-case 5.2.1 → 5.3.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: 007b0e8ba30a51777bce3c5665960238f0fe50d33c04d3102e444dd917d7a762
4
- data.tar.gz: d19a095e0540f218bc4a8dba0601999a3decc56a6990be10fe4a5ef7e35e31c8
3
+ metadata.gz: 936bb237d3decf217151d48e7f32339ac698d65bde22930a05e4b90e92d760ea
4
+ data.tar.gz: e9ecc10a25c778a1393f803bd32ad6ebf7481c1a9144a4d0ac0fce843aed53d2
5
5
  SHA512:
6
- metadata.gz: f96b58e62d5fa9de89a664b748941ee4762a9bf4f58b83aa7a56fa745b447772b33df24272aa8d49b3768ce6d83a2af9138647baf2d1e704276db2f7ca335cdc
7
- data.tar.gz: 6260ad743a4a40da49d0bbd7cea4d5d7aba9ce374bce2df8bc496d61373b11de3c7315017936a8053625ba5298b4e8fb13d03c748ceccdd73c590690bffff366
6
+ metadata.gz: 5a17f2832229d00b96976ebd9d75053b2a0790625ebc8323e2d2def3d7f90d8aa78a255c834a53e7dcf88b578c9c7ba294a1097b317d0a0f74a579f1c29986a4
7
+ data.tar.gz: 5a357a9a1cbcd6487c62259f85316304348171de648d1bdf35193b92a2952bfc9a51d98d4e16f0572eb7d4e64e12d1c511e161235b3a092176712abcc5e87157
data/CHANGELOG.md ADDED
@@ -0,0 +1,524 @@
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.3.1] - 2026-05-23
11
+ ### Added
12
+ - 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.
13
+ - `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.
14
+
15
+ ## [5.3.0] - 2026-05-23
16
+ ### Added
17
+ - `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).
18
+ - README "Safe" section now documents how to opt out via `disable_safe_features`.
19
+
20
+ ## [5.2.1] - 2026-05-23
21
+ ### Fixed
22
+ - 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.
23
+
24
+ ### Added
25
+ - `ruby-lsp` as a development dependency on Ruby >= 3.0.
26
+ - 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.
27
+
28
+ ## [5.2.0] - 2026-05-23
29
+ ### Changed
30
+ - `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).
31
+ - 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.
32
+ - READMEs (EN + pt-BR) now document the `accept:` / `reject:` attribute validation flow.
33
+
34
+ ### Removed
35
+ - 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.
36
+
37
+ ### Fixed
38
+ - Gate the `minitest` development dependency on Ruby version.
39
+
40
+ ## [5.1.0] - 2026-05-23
41
+ ### Added
42
+ - `Micro::Case::Result#keys`, `#fetch` and `#fetch_values` for `Hash`-like access to the result data (PR #127, thanks @tomascco).
43
+ - pt-BR README documentation for the new `Result` methods.
44
+
45
+ ## [5.0.0] - 2026-05-23
46
+ ### Changed
47
+ - **BREAKING:** Bumped minimum Ruby to **2.7.0** (Ruby 2.2 – 2.6 are EOL and no longer supported).
48
+ - 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`.
49
+ - 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.
50
+ - Switched code coverage reporting from CodeClimate to **Qlty** (OIDC-based upload, badges updated in both READMEs).
51
+ - README polish: new header/badge layout, Ruby × Rails support matrix, refreshed compatibility table, and pt-BR typo fixes.
52
+
53
+ ### Added
54
+ - Appraisal-generated gemfiles for **Rails 8.1** and **Rails edge**.
55
+ - `bin/matrix` script and `rake matrix` task to run the full local test matrix.
56
+ - `bin/setup` script.
57
+
58
+ ### Removed
59
+ - Per-Rails subdirectory gemfiles under `gemfiles/rails_5.2…rails_edge/` (replaced by Appraisal).
60
+ - `pry-byebug` from the test helper (dev-only convenience, no longer required).
61
+
62
+ ### Security
63
+ - 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).
64
+
65
+ ## [4.5.2] - 2022-12-05
66
+ ### Added
67
+ - Add Ruby 3.1 to the test matrix.
68
+
69
+ ### Changed
70
+ - Migrate CI from Travis CI to GitHub Actions.
71
+
72
+ ### Fixed
73
+ - Rename `Micro::Case::Utils::Hashes.respond_to?` to `hash_respond_to?` so it no longer overrides Ruby's default `respond_to?`.
74
+ - Return the generated flow-step class explicitly so flow definitions stay compatible with Ruby 3.1.
75
+ - Restore `Micro::Cases.map` behavior on Ruby 2.5 (avoid `return` inside the inner lambda).
76
+
77
+ ## [4.5.1] - 2021-06-08
78
+ ### Fixed
79
+ - Stop invoking `on_unknown` after a matching `on_exception` hook has already handled the result.
80
+
81
+ ## [4.5.0] - 2021-06-08
82
+ ### Changed
83
+ - Bump the required `kind` runtime dependency to `>= 5.6, < 6.0`.
84
+
85
+ ## [4.4.0] - 2021-06-08
86
+ ### Changed
87
+ - 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.
88
+
89
+ ## [4.3.0] - 2021-02-22
90
+ ### Added
91
+ - `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`).
92
+ - `Result#then` now accepts a `Symbol`/`String`, calling the matching instance method on the source use case as the next step.
93
+
94
+ ### Changed
95
+ - Bump runtime dependencies: `kind` to `>= 4.0, < 6.0` and `u-attributes` to `>= 2.7, < 3.0`.
96
+ - Make the test suite Ruby 3.0 compatible.
97
+
98
+ ### Removed
99
+ - Stop registering `Micro::Case` and `Micro::Case::Result` with `Kind::Types`, dropping the `Kind::Of::Micro::Case` / `Kind::Of::Micro::Case::Result` validators.
100
+
101
+ ## [4.2.2] - 2020-12-04
102
+ ### Fixed
103
+ - 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`.
104
+
105
+ ## [4.2.1] - 2020-10-21
106
+ ### Fixed
107
+ - Make `Micro::Case`, `Micro::Case::Result`, and `Micro::Cases::Flow` `#inspect` strings start with `#<...>` and collapse recursive inspect output to `#<Class: ...>`.
108
+
109
+ ## [4.2.0] - 2020-10-19
110
+ ### Added
111
+ - `Micro::Case#transaction(adapter = :activerecord) { ... }` helper that wraps a block in `ActiveRecord::Base.transaction` and rolls back when the yielded result is a failure.
112
+
113
+ ## [4.1.1] - 2020-10-15
114
+ ### Fixed
115
+ - 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.
116
+
117
+ ## [4.1.0] - 2020-10-14
118
+ ### Added
119
+ - Allow calling a use case or flow inside another use case via the private `call(use_case, defaults = {})` helper, automatically forwarding attributes/accessible attributes.
120
+ - 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).
121
+ - `Micro::Cases.map(...)` / `Micro::Cases::Map` to fan out the same input across multiple use cases and collect their results.
122
+ - Allow dependency injection in both static (`flow A, [B, dep: ...], C`) and inner-flow definitions via `[UseCase, defaults_hash]` tuples.
123
+ - `Micro.case?(arg)` predicate (in addition to the existing `Micro.case_or_flow?`).
124
+ - Track an "unknown" result state and expose `Result#unknown?` plus the `on_unknown` hook so unhandled success/failure types can be caught.
125
+ - `Micro::Cases::Error` used for invalid use-case errors raised by flows and `Cases::Map`.
126
+ - New internals: `Micro::Cases::Utils` (`MapUseCases`, `IsAValidUseCase`, …) and a `Micro::Case::Utils::Hashes.stringify_keys` helper.
127
+
128
+ ### Changed
129
+ - `Micro::Case.new` is now a private class method — use `.call` / `.__new__` (internal) instead of constructing instances directly.
130
+ - Drop the `u-attributes` `:initialize` and `:diff` extensions; `Micro::Case` now `include Micro::Attributes` directly.
131
+ - Refine `Result#inspect` to omit the `transitions=` segment when transitions are disabled.
132
+
133
+ ### Fixed
134
+ - Fix inner flows declared with an array argument.
135
+
136
+ ## [4.0.0] - 2020-08-20
137
+ Major rewrite. The headline shifts:
138
+ - `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.
139
+ - The gem now requires the brand-new `u-attributes ~> 2.0` runtime, which changes how attribute inheritance works for `Micro::Case` subclasses.
140
+ - The `Micro::Case::Result` transitions mapper now always defaults to `Transitions::MapEverything`.
141
+
142
+ ### Added
143
+ - `Micro::Case::Result#to_sym` returning `:success` or `:failure`.
144
+
145
+ ### Changed
146
+ - **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.
147
+ - Refactor `Micro::Case::Result` construction so `transitions_mapper` defaults to `Transitions::MapEverything` directly and `MapEverything` uses `result.to_sym` instead of an intermediate local.
148
+ - Update gem summary/description to "Represent use cases in a simple and powerful way while writing modular, expressive and sequentially logical code."
149
+
150
+ ### Removed
151
+ - Remove the `--pre` flag references from the docs/install instructions now that 4.x ships as a stable release.
152
+
153
+ ## [3.1.0] - 2020-08-17
154
+ ### Added
155
+ - `Micro::Case#apply` as a private alias for `#method` to make internal step composition more idiomatic.
156
+ - `Micro::Case::Result::Transitions` extracted as a dedicated class to model the sequence of steps executed by a use case / flow.
157
+
158
+ ### Changed
159
+ - Freeze `Micro::Case::Result#data` so the accumulated payload cannot be mutated by callers.
160
+ - Internal refactor of `Micro::Case::Result` and minor README/translation polish.
161
+
162
+ ### Fixed
163
+ - Improve handling and error feedback when `Micro::Case::Result#then` is invoked with an invalid argument.
164
+
165
+ ## [3.0.0] - 2020-08-14
166
+ Major rewrite consolidating nine release candidates. Highlights:
167
+
168
+ ### Added
169
+ - New flow builders `Micro::Cases.flow(...)` and `Micro::Cases.safe_flow(...)` replacing the previous `Micro::Case::Flow()` / `Micro::Case::Safe::Flow()` constructors.
170
+ - `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.
171
+ - `Micro::Case::Result#transitions` exposing the ordered history of steps executed during a use case / flow.
172
+ - `Micro::Case.config` for global configuration (e.g. enabling/disabling transitions tracking, ActiveModel validation).
173
+ - `Micro::Case.then` and `Micro::Cases::Flow#then` so use cases and flows can be chained.
174
+ - `Micro::Case::Result#then` / `Result#|` accept a `Micro::Case` class, a flow, a method instance or a block, and accumulate data across the chain.
175
+ - Declare a use case's steps by referencing its own private methods.
176
+ - Top-level introspection helpers `Micro.case?` and `Micro.case_or_flow?`.
177
+ - Success results expose the use case instance that produced them.
178
+
179
+ ### Changed
180
+ - **BREAKING:** `Success`/`Failure` results are now declared via the `result:` keyword argument instead of a block (e.g. `Success(result: { ... })`).
181
+ - **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.
182
+ - **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`.
183
+ - Bumped the `kind` gem to the next major version.
184
+ - Only two ways to define a flow are now supported; the legacy `Flow::Reducer` was removed.
185
+
186
+ ### Removed
187
+ - **BREAKING:** `Micro::Case#call` instance method — use cases are invoked via the class-level API.
188
+ - **BREAKING:** `Micro::Case::Flow()` and `Micro::Case::Safe::Flow()` constructors (replaced by `Micro::Cases.flow` / `Micro::Cases.safe_flow`).
189
+ - The deprecated `u-case/with_validation` shim file.
190
+
191
+ ### Fixed
192
+ - Internal steps and flow execution behave correctly when result transitions tracking is disabled.
193
+ - Internal steps that receive a method instance now use keyword arguments (`**`) consistently.
194
+
195
+ ## [3.0.0.rc9] - 2020-08-14
196
+ ### Changed
197
+ - Internal steps that receive a method instance now use keyword arguments for parameter passing.
198
+
199
+ ## [3.0.0.rc8] - 2020-08-14
200
+ ### Fixed
201
+ - Flow execution when result transitions are disabled.
202
+ - Internal steps that receive a method instance now use the double-splat operator.
203
+
204
+ ## [3.0.0.rc7] - 2020-08-13
205
+ ### Fixed
206
+ - Internal steps when result transitions are disabled.
207
+
208
+ ## [3.0.0.rc6] - 2020-08-12
209
+ ### Added
210
+ - `Micro::Case::Result#then` / `Result#|` accept a method instance, in addition to a block or use case.
211
+
212
+ ### Changed
213
+ - `Micro::Case::Result#then` / `Result#|` now accumulate data across the chain.
214
+ - Default branch references migrated from `master` to `main`.
215
+
216
+ ## [3.0.0.rc5] - 2020-08-12
217
+ ### Added
218
+ - `Micro::Case.then` and `Micro::Cases::Flow#then` so use cases and flows can be chained.
219
+ - `Micro::Case::Result#key?`, `Result#value?` and `Result#slice` for ergonomic data access.
220
+
221
+ ### Changed
222
+ - Renamed inner flow constant `Flow_Step` to `Self`.
223
+ - Refactored `Micro::Cases::Flow` input handling.
224
+ - pt-BR README translation introduced; READMEs, logo and assets refreshed.
225
+
226
+ ## [3.0.0.rc4] - 2020-08-02
227
+ ### Added
228
+ - Declare use case steps by referencing private methods of the use case.
229
+ - Top-level introspection helpers `Micro.case?` and `Micro.case_or_flow?`.
230
+
231
+ ### Changed
232
+ - **BREAKING:** Static public methods of `Micro::Case` renamed to the new convention.
233
+ - Validate the output of lambdas passed to `Micro::Case::Result#then` / `Result#|`.
234
+ - Result transitions now also include the steps coming from internal step methods.
235
+
236
+ ### Removed
237
+ - **BREAKING:** `Micro::Case#call` instance method.
238
+
239
+ ## [3.0.0.rc3] - 2020-07-29
240
+ ### Added
241
+ - `Micro::Case.config` for global configuration of the library (e.g. transitions tracking, ActiveModel validation).
242
+ - Success results now expose the use case instance that produced them.
243
+
244
+ ## [3.0.0.rc2] - 2020-07-28
245
+ ### Changed
246
+ - Prepare for the next major version of the `kind` gem.
247
+ - Refactor `Micro::Case::Error::InvalidResult` and improve the error message raised when a use case returns the wrong result type.
248
+
249
+ ### Removed
250
+ - The deprecated `lib/u-case/with_validation.rb` shim.
251
+
252
+ ## [3.0.0.rc1] - 2020-07-21
253
+ ### Added
254
+ - New flow builders `Micro::Cases.flow(...)` / `Micro::Cases.safe_flow(...)`.
255
+ - `Micro::Case::Result#data` exposing the accumulated payload, plus `Result#[]` and `Result#values_at`.
256
+ - `Micro::Case::Result#transitions` exposing the ordered history of executed steps.
257
+ - Result payloads can now be initialized from a `Hash`, `Symbol` or `Exception`.
258
+
259
+ ### Changed
260
+ - **BREAKING:** `Success`/`Failure` results are now declared via the `result:` keyword argument instead of a block.
261
+ - **BREAKING:** `Micro::Case::Result#then` now yields the result itself and returns the block's value.
262
+ - **BREAKING:** Only two ways to define a flow are supported; the legacy `Flow::Reducer` was removed.
263
+ - Defining an invalid success/failure result now raises an explicit error.
264
+
265
+ ### Removed
266
+ - **BREAKING:** `Micro::Case::Flow()` and `Micro::Case::Safe::Flow()` constructors — use `Micro::Cases.flow` / `Micro::Cases.safe_flow` instead.
267
+
268
+ ## [2.6.0] - 2020-07-07
269
+ ### Added
270
+ - New behavior for `Micro::Case::Result#then` to chain another use case from a result.
271
+
272
+ ### Fixed
273
+ - `Micro::Case::Result#transitions` no longer produces incorrect/duplicated entries when chaining via `#then`.
274
+
275
+ ## [2.5.0] - 2020-06-26
276
+ ### Added
277
+ - `Micro::Case::Result#on_exception` hook to handle exceptions raised inside a use case.
278
+
279
+ ### Changed
280
+ - Forbid inheritance from a use case that defines an inner flow (raises an explicit error instead of silently misbehaving).
281
+
282
+ ## [2.4.0] - 2020-06-26
283
+ ### Added
284
+ - New file `u-case/with_activemodel_validation` so projects can opt into the ActiveModel-backed validation flavor explicitly.
285
+ - `Micro::Case::Utils` helper module.
286
+ - `Kind.of.Micro::Case::Result` type checker (via the new `kind` runtime dependency).
287
+ - `Micro::Case::Result#transitions` exposing the step-by-step history of a flow, including `:accessible_attributes` for each step.
288
+ - `Micro::Case::Result.disable_transition_tracking` configuration to opt out of transition tracking.
289
+ - New built-in support for validations via `Kind::Validator` (alongside ActiveModel).
290
+ - The use case instance is now exposed on successful results.
291
+
292
+ ### Changed
293
+ - `kind` is now a runtime dependency (bumped to `~> 3.0`).
294
+ - `require "u-case/with_validation"` now also loads the ActiveModel-based validation layer for backward compatibility.
295
+
296
+ ## [2.3.1] - 2019-12-29
297
+ ### Fixed
298
+ - Use-case validation no longer breaks when the class also declares a flow.
299
+
300
+ ## [2.3.0] - 2019-12-17
301
+ ### Added
302
+ - `Micro::Case::Result#then` to pipe a successful result into another use case (or block).
303
+ - Clearer error messages raised by `Micro::Case` when misused.
304
+
305
+ ## [2.2.0] - 2019-12-12
306
+ ### Added
307
+ - The flow definition (`flow ...`) can now be declared independently of the attribute declarations, making class layout more flexible.
308
+
309
+ ## [2.1.1] - 2019-12-12
310
+ ### Fixed
311
+ - Flow execution when a participating use case declares validations.
312
+
313
+ ## [2.1.0] - 2019-12-12
314
+ ### Added
315
+ - A `Micro::Case` subclass can declare its own internal flow and include itself in that flow.
316
+
317
+ ### Deprecated
318
+ - The `Micro::Case::Flow` mixin — declare flows directly on the use case class instead.
319
+
320
+ ## [2.0.0] - 2019-11-19
321
+ First stable 2.0 release. Includes everything from the 2.0.0.pre series plus:
322
+
323
+ ### Added
324
+ - Per-class opt-out from the automatic validation step (`disable_auto_validation`).
325
+
326
+ ## [2.0.0.pre.4] - 2019-11-19
327
+ ### Changed
328
+ - A flow now accumulates the success results of each step and feeds the merged data as input into the next use case.
329
+ - Renamed the custom test assertion helpers for `Micro::Case::Result` objects (final naming).
330
+
331
+ ## [2.0.0.pre.3] - 2019-11-14
332
+ ### Fixed
333
+ - `Micro::Case::Safe.Flow()` definition.
334
+ - `on_failure` without an explicit type now exposes a `Micro::Case::Result::Data` value instead of leaking internals.
335
+
336
+ ## [2.0.0.pre.2] - 2019-11-13
337
+ ### Changed
338
+ - New API for defining flows that operate over collections.
339
+
340
+ ## [2.0.0.pre] - 2019-11-12
341
+ ### Changed
342
+ - **BREAKING:** `Micro::Case::Base` was merged into `Micro::Case` — inherit from `Micro::Case` directly.
343
+ - **BREAKING:** `Micro::Case::Flow::Safe` was renamed to `Micro::Case::Safe::Flow`.
344
+ - Filenames using the old `pipeline` terminology were renamed to `flow`.
345
+
346
+ ### Added
347
+ - New custom Minitest assertions for `Micro::Case::Result` (`assert_success_result`, `assert_failure_result`, `assert_result`).
348
+
349
+ ## [1.1.0] - 2019-10-04
350
+ ### Changed
351
+ - Validation failure results now expose their errors as a `Hash` for consistent destructuring.
352
+
353
+ ## [1.0.0] - 2019-09-15
354
+ First release under the `u-case` name (renamed from `u-service`).
355
+
356
+ ### Changed
357
+ - **BREAKING:** Gem renamed from `u-service` to `u-case`.
358
+ - **BREAKING:** `Micro::Service` namespace renamed to `Micro::Case` — update all references (`Micro::Service::Base` → `Micro::Case::Base`, `Micro::Service::Strict` → `Micro::Case::Strict`, etc.).
359
+ - **BREAKING:** The "pipeline" concept was renamed to "flow" throughout the public API (`Micro::Service::Pipeline` → `Micro::Case::Flow`).
360
+
361
+ ---
362
+
363
+ ## Pre-rename history (published as `u-service`)
364
+
365
+ ## [u-service 1.0.0] - 2019-08-25
366
+ ### Added
367
+ - `Micro::Service::Safe` and `Micro::Service::Strict::Safe`: service variants that rescue exceptions and return them as failure results.
368
+ - Safe pipelines that intercept exceptions raised inside services; the failing service instance is exposed on the resulting failure.
369
+ - `Micro::Service::Error` module gathering all gem-specific exceptions in one namespace.
370
+ - `to_proc` on services and pipelines, enabling use with iterators like `map(&MyService)`.
371
+ - `:exception` is returned as the result type whenever a failure value is an `Exception`.
372
+ - When a failure is invoked with a `Symbol`, that symbol is used as both the result type and value.
373
+
374
+ ### Changed
375
+ - 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.
376
+ - Pipeline reducers extracted into their own files; safe-pipeline reducer reworked for clarity.
377
+ - Default failure type for safe services improved so rescued exceptions produce a consistent `:exception` type.
378
+
379
+ ## [u-service 0.14.0] - 2019-08-19
380
+ ### Added
381
+ - 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.
382
+
383
+ ### Changed
384
+ - Improved error messages when an invalid value is assigned as a result.
385
+
386
+ ## [u-service 0.13.1] - 2019-08-19
387
+ ### Changed
388
+ - Slimmed the published gem by excluding files unnecessary at runtime.
389
+
390
+ ## [u-service 0.13.0] - 2019-08-19
391
+ ### Added
392
+ - `require 'u-service/with_validation'` shortcut to enable the ActiveModel-validation mode.
393
+ - Default result types: `:ok` for success and `:error` for failure when none is provided.
394
+ - New `:validation_error` result type returned automatically when a validated service is invalid.
395
+
396
+ ### Changed
397
+ - Result `type` is always coerced to a `Symbol`.
398
+ - The validation mode now modifies the base class on load rather than exposing separate `Validation` classes, simplifying the public API.
399
+
400
+ ### Removed
401
+ - The internal `Validation` classes layer (superseded by the base-class extension above).
402
+
403
+ ## [u-service 0.12.0] - 2019-08-14
404
+ ### Changed
405
+ - Reduced object allocation while processing a pipeline, improving throughput.
406
+
407
+ ## [u-service 0.11.0] - 2019-08-13
408
+ ### Added
409
+ - Pipelines defined as classes are now validated at definition time, surfacing configuration mistakes earlier.
410
+ - Pipelines can be composed of other `Micro::Service` abstractions (services and pipelines used interchangeably as steps).
411
+
412
+ ## [u-service 0.10.0] - 2019-08-10
413
+ ### Added
414
+ - Composition operator for building a pipeline from services and/or other pipelines (e.g. `ServiceA >> ServiceB`).
415
+
416
+ ## [u-service 0.9.0] - 2019-08-09
417
+ ### Added
418
+ - `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.
419
+
420
+ ## [u-service 0.8.0] - 2019-08-08
421
+ ### Added
422
+ - Alternative class-level DSL for declaring pipelines inside a class (in addition to `Micro::Service::Pipeline[...]`).
423
+
424
+ ## [u-service 0.7.0] - 2019-08-06
425
+ ### Changed
426
+ - Optimized `Micro::Service::Pipeline` execution.
427
+
428
+ ## [u-service 0.6.0] - 2019-08-06
429
+ ### Added
430
+ - `Micro::Service::WithValidation`, integrating ActiveModel validations into services so invalid input short-circuits with a failure.
431
+ - CI matrix expanded to run against multiple ActiveModel versions.
432
+
433
+ ## [u-service 0.5.0] - 2019-08-06
434
+ ### Added
435
+ - Pipelines can be called with an existing `Result` as their starting input, enabling chaining across pipelines.
436
+
437
+ ### Changed
438
+ - Renamed `Micro::Service::Strict::Base` to `Micro::Service::Strict`.
439
+
440
+ ### Removed
441
+ - `Micro::Service::Strict::Base` (replaced by `Micro::Service::Strict`).
442
+
443
+ ## [u-service 0.4.0] - 2019-08-05
444
+ ### Added
445
+ - `Micro::Service::Result#type` is now validated (must be a non-blank symbol/string).
446
+
447
+ ### Changed
448
+ - **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.
449
+
450
+ ## [u-service 0.3.0] - 2019-08-05
451
+ ### Added
452
+ - `Micro::Service::Pipeline` — compose multiple services into a single callable pipeline via `Micro::Service::Pipeline[ServiceA, ServiceB, ...]`.
453
+ - Argument validation for `Micro::Service::Pipeline[]` to catch bad pipeline definitions up front.
454
+
455
+ ## [u-service 0.2.0] - 2019-08-05
456
+ ### Added
457
+ - `Micro::Service::Strict::Base` — a strict variant that enforces that all declared attributes are provided.
458
+
459
+ ## [u-service 0.1.0] - 2019-08-05
460
+ ### Added
461
+ - Initial release of `u-service`.
462
+ - `Micro::Service::Base`: define services with attribute-based input and a `call!` method.
463
+ - `Micro::Service::Result` with `Success`/`Failure` factories and helper methods for returning typed results from services.
464
+ - Runtime dependency on `u-attributes` for service input declaration.
465
+
466
+ [5.3.1]: https://github.com/serradura/u-case/compare/v5.3.0...v5.3.1
467
+ [5.3.0]: https://github.com/serradura/u-case/compare/v5.2.1...v5.3.0
468
+ [5.2.1]: https://github.com/serradura/u-case/compare/v5.2.0...v5.2.1
469
+ [5.2.0]: https://github.com/serradura/u-case/compare/v5.1.0...v5.2.0
470
+ [5.1.0]: https://github.com/serradura/u-case/compare/v5.0.0...v5.1.0
471
+ [5.0.0]: https://github.com/serradura/u-case/compare/v4.5.2...v5.0.0
472
+ [4.5.2]: https://github.com/serradura/u-case/compare/v4.5.1...v4.5.2
473
+ [4.5.1]: https://github.com/serradura/u-case/compare/v4.5.0...v4.5.1
474
+ [4.5.0]: https://github.com/serradura/u-case/compare/v4.4.0...v4.5.0
475
+ [4.4.0]: https://github.com/serradura/u-case/compare/v4.3.0...v4.4.0
476
+ [4.3.0]: https://github.com/serradura/u-case/compare/v4.2.2...v4.3.0
477
+ [4.2.2]: https://github.com/serradura/u-case/compare/v4.2.1...v4.2.2
478
+ [4.2.1]: https://github.com/serradura/u-case/compare/v4.2.0...v4.2.1
479
+ [4.2.0]: https://github.com/serradura/u-case/compare/v4.1.1...v4.2.0
480
+ [4.1.1]: https://github.com/serradura/u-case/compare/v4.1.0...v4.1.1
481
+ [4.1.0]: https://github.com/serradura/u-case/compare/v4.0.0...v4.1.0
482
+ [4.0.0]: https://github.com/serradura/u-case/compare/v3.1.0...v4.0.0
483
+ [3.1.0]: https://github.com/serradura/u-case/compare/v3.0.0...v3.1.0
484
+ [3.0.0]: https://github.com/serradura/u-case/compare/v3.0.0.rc9...v3.0.0
485
+ [3.0.0.rc9]: https://github.com/serradura/u-case/compare/v3.0.0.rc8...v3.0.0.rc9
486
+ [3.0.0.rc8]: https://github.com/serradura/u-case/compare/v3.0.0.rc7...v3.0.0.rc8
487
+ [3.0.0.rc7]: https://github.com/serradura/u-case/compare/v3.0.0.rc6...v3.0.0.rc7
488
+ [3.0.0.rc6]: https://github.com/serradura/u-case/compare/v3.0.0.rc5...v3.0.0.rc6
489
+ [3.0.0.rc5]: https://github.com/serradura/u-case/compare/v3.0.0.rc4...v3.0.0.rc5
490
+ [3.0.0.rc4]: https://github.com/serradura/u-case/compare/v3.0.0.rc3...v3.0.0.rc4
491
+ [3.0.0.rc3]: https://github.com/serradura/u-case/compare/v3.0.0.rc2...v3.0.0.rc3
492
+ [3.0.0.rc2]: https://github.com/serradura/u-case/compare/v3.0.0.rc1...v3.0.0.rc2
493
+ [3.0.0.rc1]: https://github.com/serradura/u-case/compare/v2.6.0...v3.0.0.rc1
494
+ [2.6.0]: https://github.com/serradura/u-case/compare/v2.5.0...v2.6.0
495
+ [2.5.0]: https://github.com/serradura/u-case/compare/v2.4.0...v2.5.0
496
+ [2.4.0]: https://github.com/serradura/u-case/compare/v2.3.1...v2.4.0
497
+ [2.3.1]: https://github.com/serradura/u-case/compare/v2.3.0...v2.3.1
498
+ [2.3.0]: https://github.com/serradura/u-case/compare/v2.2.0...v2.3.0
499
+ [2.2.0]: https://github.com/serradura/u-case/compare/v2.1.1...v2.2.0
500
+ [2.1.1]: https://github.com/serradura/u-case/compare/v2.1.0...v2.1.1
501
+ [2.1.0]: https://github.com/serradura/u-case/compare/v2.0.0...v2.1.0
502
+ [2.0.0]: https://github.com/serradura/u-case/compare/v2.0.0.pre.4...v2.0.0
503
+ [2.0.0.pre.4]: https://github.com/serradura/u-case/compare/v2.0.0.pre.3...v2.0.0.pre.4
504
+ [2.0.0.pre.3]: https://github.com/serradura/u-case/compare/v2.0.0.pre.2...v2.0.0.pre.3
505
+ [2.0.0.pre.2]: https://github.com/serradura/u-case/compare/v2.0.0.pre...v2.0.0.pre.2
506
+ [2.0.0.pre]: https://github.com/serradura/u-case/compare/v1.1.0...v2.0.0.pre
507
+ [1.1.0]: https://github.com/serradura/u-case/compare/v1.0.0...v1.1.0
508
+ [1.0.0]: https://github.com/serradura/u-case/compare/u-service-v1.0.0...v1.0.0
509
+ [u-service 1.0.0]: https://github.com/serradura/u-case/compare/u-service-v0.14.0...u-service-v1.0.0
510
+ [u-service 0.14.0]: https://github.com/serradura/u-case/compare/u-service-v0.13.1...u-service-v0.14.0
511
+ [u-service 0.13.1]: https://github.com/serradura/u-case/compare/u-service-v0.13.0...u-service-v0.13.1
512
+ [u-service 0.13.0]: https://github.com/serradura/u-case/compare/u-service-v0.12.0...u-service-v0.13.0
513
+ [u-service 0.12.0]: https://github.com/serradura/u-case/compare/u-service-v0.11.0...u-service-v0.12.0
514
+ [u-service 0.11.0]: https://github.com/serradura/u-case/compare/u-service-v0.10.0...u-service-v0.11.0
515
+ [u-service 0.10.0]: https://github.com/serradura/u-case/compare/u-service-v0.9.0...u-service-v0.10.0
516
+ [u-service 0.9.0]: https://github.com/serradura/u-case/compare/u-service-v0.8.0...u-service-v0.9.0
517
+ [u-service 0.8.0]: https://github.com/serradura/u-case/compare/u-service-v0.7.0...u-service-v0.8.0
518
+ [u-service 0.7.0]: https://github.com/serradura/u-case/compare/u-service-v0.6.0...u-service-v0.7.0
519
+ [u-service 0.6.0]: https://github.com/serradura/u-case/compare/u-service-v0.5.0...u-service-v0.6.0
520
+ [u-service 0.5.0]: https://github.com/serradura/u-case/compare/u-service-v0.4.0...u-service-v0.5.0
521
+ [u-service 0.4.0]: https://github.com/serradura/u-case/compare/u-service-v0.3.0...u-service-v0.4.0
522
+ [u-service 0.3.0]: https://github.com/serradura/u-case/compare/u-service-v0.2.0...u-service-v0.3.0
523
+ [u-service 0.2.0]: https://github.com/serradura/u-case/compare/u-service-v0.1.0...u-service-v0.2.0
524
+ [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,111 @@
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
+ ## Bumping the version
97
+
98
+ 1. Edit `lib/micro/case/version.rb` — change `Micro::Case::VERSION`. Follow
99
+ [SemVer](https://semver.org/): patch for fixes, minor for additive
100
+ user-visible changes, major for breaking changes.
101
+ 2. Add a new top entry in `CHANGELOG.md` (`## [X.Y.Z] - YYYY-MM-DD`) and a
102
+ matching compare link at the bottom (`[X.Y.Z]: …/compare/vPREV...vX.Y.Z`).
103
+ 3. Update both READMEs:
104
+ - **Documentation** table → bump the `v5.x` (or current major) row's
105
+ version label.
106
+ - **Compatibility** table → if dependency bounds changed, add a new row;
107
+ otherwise bump the existing row's version label.
108
+ 4. If `Gemfile`/`u-case.gemspec` dependency bounds moved, double-check the
109
+ Compatibility table and `Appraisals` reflect the new bounds.
110
+
111
+ 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.3.1 | 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).
@@ -60,6 +60,7 @@ unreleased| https://github.com/serradura/u-case/blob/main/README.md
60
60
  - [`Micro::Case::Safe` - Is there some feature to auto handle exceptions inside of a use case or flow?](#microcasesafe---is-there-some-feature-to-auto-handle-exceptions-inside-of-a-use-case-or-flow)
61
61
  - [`Micro::Cases::Safe::Flow`](#microcasessafeflow)
62
62
  - [`Micro::Case::Result#on_exception`](#microcaseresulton_exception)
63
+ - [Opting out of the safe mechanism](#opting-out-of-the-safe-mechanism)
63
64
  - [Validating attributes with `accept:` / `reject:`](#validating-attributes-with-accept--reject)
64
65
  - [`u-case/with_activemodel_validation` - How to validate the use case attributes?](#u-casewith_activemodel_validation---how-to-validate-the-use-case-attributes)
65
66
  - [If I enabled the auto validation, is it possible to disable it only in specific use cases?](#if-i-enabled-the-auto-validation-is-it-possible-to-disable-it-only-in-specific-use-cases)
@@ -89,7 +90,7 @@ unreleased| https://github.com/serradura/u-case/blob/main/README.md
89
90
  | u-case | branch | ruby | activemodel | u-attributes |
90
91
  | ---------------- | ------ | -------- | -------------- | -------------- |
91
92
  | unreleased | main | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
92
- | 5.2.1 | v5.x | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
93
+ | 5.3.1 | v5.x | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
93
94
  | 5.1.0 | v5.x | >= 2.7 | >= 6.0 | >= 2.7, < 4.0 |
94
95
  | 4.5.1 | v4.x | >= 2.2.0 | >= 3.2, <= 8.1 | >= 2.7, < 3.0 |
95
96
 
@@ -1070,6 +1071,28 @@ As you can see, this hook has the same behavior of `result.on_failure(:exception
1070
1071
 
1071
1072
  [⬆️ Back to Top](#table-of-contents-)
1072
1073
 
1074
+ #### Opting out of the safe mechanism
1075
+
1076
+ The "safe" mechanism is opinionated: it converts any unhandled exception inside a use case (or any step of a flow) into a failure result with `type: :exception`. That is powerful, but it can also produce a **fragmented codebase**, where some exceptions are handled with `rescue` inside `call!` and others are handled later via `on_exception` / `on_failure(:exception)` — making the control flow hard to reason about.
1077
+
1078
+ If you prefer a single, explicit convention for exception handling — namely, plain `rescue` statements inside your use cases — you can disable the safe APIs entirely:
1079
+
1080
+ ```ruby
1081
+ Micro::Case.config do |config|
1082
+ config.disable_safe_features = true
1083
+ end
1084
+ ```
1085
+
1086
+ Once enabled, the following will raise `Micro::Case::Error::SafeFeaturesDisabled`, ensuring no one in the codebase can reintroduce the safe path by accident:
1087
+
1088
+ - Subclassing `Micro::Case::Safe`
1089
+ - Calling `Micro::Cases.safe_flow(...)`
1090
+ - Calling `Micro::Case::Result#on_exception`
1091
+
1092
+ See [`Micro::Case.config`](#microcaseconfig) for the full list of available toggles.
1093
+
1094
+ [⬆️ Back to Top](#table-of-contents-)
1095
+
1073
1096
  ### Validating attributes with `accept:` / `reject:`
1074
1097
 
1075
1098
  Since `u-case 5.2.0`, every use case includes the [`accept` extension](https://github.com/serradura/u-attributes#accept-extension) from [`u-attributes`](https://github.com/serradura/u-attributes) (requires `u-attributes >= 2.8`). You can declare type expectations (or any other check) directly on the attribute, and the use case will fail automatically with the `:invalid_attributes` type when any attribute is rejected — no need to validate inside `call!`.
@@ -1225,6 +1248,14 @@ Micro::Case.config do |config|
1225
1248
 
1226
1249
  # Use to enable/disable the `Micro::Case::Results#transitions`.
1227
1250
  config.enable_transitions = true
1251
+
1252
+ # Use to forbid the "safe" features and ensure a single way to handle exceptions
1253
+ # (via standard `rescue` statements). When set to `true`, the following will raise
1254
+ # `Micro::Case::Error::SafeFeaturesDisabled`:
1255
+ # - Subclassing `Micro::Case::Safe`
1256
+ # - Calling `Micro::Cases.safe_flow(...)`
1257
+ # - Calling `Micro::Case::Result#on_exception`
1258
+ config.disable_safe_features = false
1228
1259
  end
1229
1260
  ```
1230
1261
 
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.3.1 | 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 -->
@@ -58,6 +58,7 @@ unreleased| https://github.com/serradura/u-case/blob/main/README.md
58
58
  - [`Micro::Case::Safe` - Existe algum recurso para lidar automaticamente com exceções dentro de um caso de uso ou fluxo?](#microcasesafe---existe-algum-recurso-para-lidar-automaticamente-com-exceções-dentro-de-um-caso-de-uso-ou-fluxo)
59
59
  - [`Micro::Cases::Safe::Flow`](#microcasessafeflow)
60
60
  - [`Micro::Case::Result#on_exception`](#microcaseresulton_exception)
61
+ - [Desabilitando o mecanismo "safe"](#desabilitando-o-mecanismo-safe)
61
62
  - [Validando atributos com `accept:` / `reject:`](#validando-atributos-com-accept--reject)
62
63
  - [`u-case/with_activemodel_validation` - Como validar os atributos do caso de uso?](#u-casewith_activemodel_validation---como-validar-os-atributos-do-caso-de-uso)
63
64
  - [Se eu habilitei a validação automática, é possível desabilitá-la apenas em casos de uso específicos?](#se-eu-habilitei-a-validação-automática-é-possível-desabilitá-la-apenas-em-casos-de-uso-específicos)
@@ -87,7 +88,7 @@ unreleased| https://github.com/serradura/u-case/blob/main/README.md
87
88
  | u-case | branch | ruby | activemodel | u-attributes |
88
89
  | ---------------- | ------ | -------- | -------------- | -------------- |
89
90
  | unreleased | main | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
90
- | 5.2.1 | v5.x | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
91
+ | 5.3.1 | v5.x | >= 2.7 | >= 6.0 | >= 2.8, < 4.0 |
91
92
  | 5.1.0 | v5.x | >= 2.7 | >= 6.0 | >= 2.7, < 4.0 |
92
93
  | 4.5.1 | v4.x | >= 2.2.0 | >= 3.2, <= 8.1 | >= 2.7, < 3.0 |
93
94
 
@@ -1071,6 +1072,28 @@ Como você pode ver, este hook tem o mesmo comportamento de `result.on_failure(:
1071
1072
 
1072
1073
  [⬆️ Voltar para o índice](#índice-)
1073
1074
 
1075
+ #### Desabilitando o mecanismo "safe"
1076
+
1077
+ O mecanismo "safe" é opinativo: ele converte qualquer exceção não tratada dentro de um caso de uso (ou em qualquer passo de um fluxo) em um resultado de falha com `type: :exception`. Isso é poderoso, mas também pode gerar uma **base de código fragmentada**, onde algumas exceções são tratadas com `rescue` dentro do `call!` e outras só são tratadas mais tarde via `on_exception` / `on_failure(:exception)` — tornando o fluxo de controle difícil de acompanhar.
1078
+
1079
+ Se você prefere uma única convenção explícita para o tratamento de exceções — `rescue` padrão dentro dos seus casos de uso — é possível desabilitar as APIs "safe" por completo:
1080
+
1081
+ ```ruby
1082
+ Micro::Case.config do |config|
1083
+ config.disable_safe_features = true
1084
+ end
1085
+ ```
1086
+
1087
+ Com isso ativo, os usos abaixo levantarão `Micro::Case::Error::SafeFeaturesDisabled`, garantindo que ninguém na base de código reintroduza o caminho "safe" sem querer:
1088
+
1089
+ - Herdar de `Micro::Case::Safe`
1090
+ - Chamar `Micro::Cases.safe_flow(...)`
1091
+ - Chamar `Micro::Case::Result#on_exception`
1092
+
1093
+ Veja [`Micro::Case.config`](#microcaseconfig) para a lista completa de configurações disponíveis.
1094
+
1095
+ [⬆️ Voltar para o índice](#índice-)
1096
+
1074
1097
  ### Validando atributos com `accept:` / `reject:`
1075
1098
 
1076
1099
  Desde a versão `5.2.0` do `u-case`, todo caso de uso já inclui a [extensão `accept`](https://github.com/serradura/u-attributes#accept-extension) do [`u-attributes`](https://github.com/serradura/u-attributes) (requer `u-attributes >= 2.8`). Você pode declarar a expectativa de tipo (ou qualquer outra verificação) diretamente no atributo, e o caso de uso falhará automaticamente com o tipo `:invalid_attributes` quando algum atributo for rejeitado — sem precisar validar dentro do `call!`.
@@ -1226,6 +1249,14 @@ Micro::Case.config do |config|
1226
1249
 
1227
1250
  # Use para habilitar/desabilitar o `Micro::Case::Results#transitions`.
1228
1251
  config.enable_transitions = true
1252
+
1253
+ # Use para proibir as funcionalidades "safe" e garantir uma única forma de tratar
1254
+ # exceções (via `rescue` padrão). Quando `true`, os itens abaixo levantarão
1255
+ # `Micro::Case::Error::SafeFeaturesDisabled`:
1256
+ # - Herdar de `Micro::Case::Safe`
1257
+ # - Chamar `Micro::Cases.safe_flow(...)`
1258
+ # - Chamar `Micro::Case::Result#on_exception`
1259
+ config.disable_safe_features = false
1229
1260
  end
1230
1261
  ```
1231
1262
 
@@ -13,6 +13,16 @@ module Micro
13
13
  )
14
14
  end
15
15
 
16
+ def disable_safe_features=(value)
17
+ @disable_safe_features = Kind::Boolean[value]
18
+ end
19
+
20
+ def disable_safe_features
21
+ return @disable_safe_features if defined?(@disable_safe_features)
22
+
23
+ @disable_safe_features = false
24
+ end
25
+
16
26
  def enable_activemodel_validation=(value)
17
27
  return unless Kind::Boolean[value]
18
28
 
@@ -51,6 +51,15 @@ module Micro
51
51
  end
52
52
  end
53
53
 
54
+ class SafeFeaturesDisabled < StandardError
55
+ def initialize(context)
56
+ super(
57
+ "#{context} can't be used because the safe features are disabled. " \
58
+ "To re-enable them, set `config.disable_safe_features = false`."
59
+ )
60
+ end
61
+ end
62
+
54
63
  def self.by_wrong_usage?(exception)
55
64
  case exception
56
65
  when Kind::Error, ArgumentError, InvalidResult, UnexpectedResult then true
@@ -121,6 +121,10 @@ module Micro
121
121
  end
122
122
 
123
123
  def on_exception(expected_exception = nil)
124
+ if Config.instance.disable_safe_features
125
+ raise Error::SafeFeaturesDisabled.new('Micro::Case::Result#on_exception')
126
+ end
127
+
124
128
  return self unless __failure_type?(:exception)
125
129
 
126
130
  if !expected_exception || (Kind.is?(Exception, expected_exception) && data.fetch(:exception).is_a?(expected_exception))
@@ -3,6 +3,14 @@
3
3
  module Micro
4
4
  class Case
5
5
  class Safe < ::Micro::Case
6
+ def self.inherited(subclass)
7
+ if Config.instance.disable_safe_features
8
+ raise Error::SafeFeaturesDisabled.new('Micro::Case::Safe')
9
+ end
10
+
11
+ super
12
+ end
13
+
6
14
  def self.__flow_builder__
7
15
  Cases::Safe::Flow
8
16
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  class Case
5
- VERSION = '5.2.1'.freeze
5
+ VERSION = '5.3.1'.freeze
6
6
  end
7
7
  end
data/lib/micro/case.rb CHANGED
@@ -11,9 +11,9 @@ module Micro
11
11
  require 'micro/case/utils'
12
12
  require 'micro/case/error'
13
13
  require 'micro/case/result'
14
+ require 'micro/case/config'
14
15
  require 'micro/case/safe'
15
16
  require 'micro/case/strict'
16
- require 'micro/case/config'
17
17
 
18
18
  require 'micro/cases'
19
19
 
data/lib/micro/cases.rb CHANGED
@@ -13,6 +13,10 @@ module Micro
13
13
  end
14
14
 
15
15
  def self.safe_flow(args)
16
+ if Case::Config.instance.disable_safe_features
17
+ raise Case::Error::SafeFeaturesDisabled.new('Micro::Cases.safe_flow')
18
+ end
19
+
16
20
  Safe::Flow.build(args)
17
21
  end
18
22
 
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.2.1
4
+ version: 5.3.1
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
@@ -138,7 +140,10 @@ files:
138
140
  homepage: https://github.com/serradura/u-case
139
141
  licenses:
140
142
  - MIT
141
- metadata: {}
143
+ metadata:
144
+ changelog_uri: https://github.com/serradura/u-case/blob/main/CHANGELOG.md
145
+ source_code_uri: https://github.com/serradura/u-case
146
+ bug_tracker_uri: https://github.com/serradura/u-case/issues
142
147
  rdoc_options: []
143
148
  require_paths:
144
149
  - lib