sorbet-result 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cff6b167022f8dd885a13ad6340e5c406790578043fb6ba236c26d9bec5497ec
4
- data.tar.gz: 6233fa6e5ab9b956c7bc2f57ccc11bed9c594eb01fb69dba9ce6816906968efe
3
+ metadata.gz: 445c79091954105691cf4c5d0f0084ca69ea9bee925bd8c87374b1e93d7d9811
4
+ data.tar.gz: b5e200826decd0aa68b3efe53c39cedfb34b1d3ac8807eff1af7f4ae89c36e8b
5
5
  SHA512:
6
- metadata.gz: 105c454951452c5102a768d26a99b0b004aa5004d071eb377be2f28117cdf9ad39d6596e2fc98596e936a33d3f180f2753a7734c9e25dde3e5e184aa963f6e3d
7
- data.tar.gz: 68146f7dbe9d72b97702d779825750a1e76d23b76ebd30cba6c1f9902fb9efdaab44f86847c126f4f5c54c9eebf1cab21a910f26361981ce3827054da3c56e32
6
+ metadata.gz: f4a9faca56fe08cc9c8338df268ba3d203ccfcc0ce292a63c7cbdd6e8f1532c86833b56002ef2544659834af6f0b06eb0a799dbc37cadf88a6034ae09a856f6b
7
+ data.tar.gz: 3fd929e0dc36870f908eb0c2111def18d0dc33dfd90700869cf611ddb362ecb6f0323cb6acdc9d789a07031576851593323eb47ce73bc7a987a2932f82c20010
data/CHANGELOG.md CHANGED
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [Unreleased]
8
+
9
+ ## [0.2.0] - 2023-04-21
10
+
11
+ ### Changed
12
+
13
+ - *Breaking* Updated all `T::` modules to `Typed::`. This allows the Sorbet project freedom to explore these constants in the future.
14
+ - Pulled in Zeitwerk for autoloading.
15
+
7
16
  ## [0.1.1] - 2023-04-17
8
17
 
9
18
  ### Changed
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sorbet-result (0.1.1)
5
- sorbet-runtime
4
+ sorbet-result (0.2.0)
5
+ sorbet-runtime (~> 0.5)
6
+ zeitwerk (~> 2.6)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
@@ -18,7 +19,7 @@ GEM
18
19
  json (2.6.3)
19
20
  minitest (5.18.0)
20
21
  netrc (0.11.0)
21
- parallel (1.22.1)
22
+ parallel (1.23.0)
22
23
  parser (3.2.2.0)
23
24
  ast (~> 2.4.1)
24
25
  rainbow (3.1.1)
@@ -51,14 +52,14 @@ GEM
51
52
  rubocop-sorbet (0.7.0)
52
53
  rubocop (>= 0.90.0)
53
54
  ruby-progressbar (1.13.0)
54
- sorbet (0.5.10782)
55
- sorbet-static (= 0.5.10782)
56
- sorbet-runtime (0.5.10782)
57
- sorbet-static (0.5.10782-universal-darwin-22)
58
- sorbet-static (0.5.10782-x86_64-linux)
59
- sorbet-static-and-runtime (0.5.10782)
60
- sorbet (= 0.5.10782)
61
- sorbet-runtime (= 0.5.10782)
55
+ sorbet (0.5.10792)
56
+ sorbet-static (= 0.5.10792)
57
+ sorbet-runtime (0.5.10792)
58
+ sorbet-static (0.5.10792-universal-darwin-22)
59
+ sorbet-static (0.5.10792-x86_64-linux)
60
+ sorbet-static-and-runtime (0.5.10792)
61
+ sorbet (= 0.5.10792)
62
+ sorbet-runtime (= 0.5.10792)
62
63
  spoom (1.2.1)
63
64
  sorbet (>= 0.5.10187)
64
65
  sorbet-runtime (>= 0.5.9204)
@@ -81,6 +82,7 @@ GEM
81
82
  yard-sorbet (0.8.1)
82
83
  sorbet-runtime (>= 0.5)
83
84
  yard (>= 0.9)
85
+ zeitwerk (2.6.7)
84
86
 
85
87
  PLATFORMS
86
88
  arm64-darwin-22
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # T::Result, T::Success and T::Failure
1
+ # Typed::Result, Typed::Success and Typed::Failure
2
2
 
3
3
  A simple, strongly-typed monad for modeling results, helping you implement [Railway Oriented Programming concepts](https://blog.logrocket.com/what-is-railway-oriented-programming/) in Ruby. Helps alleviate error-driven development, all the while boosting your confidence with Sorbet static checks.
4
4
 
@@ -14,50 +14,50 @@ If bundler is not being used to manage dependencies, install the gem by executin
14
14
 
15
15
  ## Usage
16
16
 
17
- Using a basic Result in your methods is as simple as indicating something could return a `T::Result`.
17
+ Using a basic Result in your methods is as simple as indicating something could return a `Typed::Result`.
18
18
 
19
19
  ```ruby
20
- sig { params(resource_id: Integer).returns(T::Result) }
20
+ sig { params(resource_id: Integer).returns(Typed::Result) }
21
21
  def call_api(resource_id)
22
22
  # something bad happened
23
- return T::Failure.new
23
+ return Typed::Failure.new
24
24
 
25
25
  # something other bad thing happened
26
- return T::Failure.new
26
+ return Typed::Failure.new
27
27
 
28
28
  # Success!
29
- T::Success.new
29
+ Typed::Success.new
30
30
  end
31
31
  ```
32
32
 
33
33
  Generally, it's nice to have a payload with results, and it's nice to have more information on failures. We can indicate what types these are in our signatures for better static checks. Note that payloads and errors can be _any_ type.
34
34
 
35
35
  ```ruby
36
- sig { params(resource_id: Integer).returns(T::Result[Float, String]) }
36
+ sig { params(resource_id: Integer).returns(Typed::Result[Float, String]) }
37
37
  def call_api(resource_id)
38
38
  # something bad happened
39
- return T::Failure.new(error: "I couldn't do it!")
39
+ return Typed::Failure.new(error: "I couldn't do it!")
40
40
 
41
41
  # something other bad thing happened
42
- return T::Failure.new(error: "I couldn't do it for another reason!")
42
+ return Typed::Failure.new(error: "I couldn't do it for another reason!")
43
43
 
44
44
  # Success!
45
- T::Success.new(payload: 1.12)
45
+ Typed::Success.new(payload: 1.12)
46
46
  end
47
47
  ```
48
48
 
49
49
  *Note:* We use Sorbet's generics for payload and error typing. The generic payload and error types are erased at runtime, so you won't get a type error at runtime if you violate the generic types. These types will help you statically so be sure to run `srb tc` on your project.
50
50
 
51
- Further, if another part of your program needs the Result, it can depend on _only_ `T::Success`es (or `T::Failure`s if you're doing something with those results).
51
+ Further, if another part of your program needs the Result, it can depend on _only_ `Typed::Success`es (or `Typed::Failure`s if you're doing something with those results).
52
52
 
53
53
  ```ruby
54
- sig { params(success_result: T::Success).void }
54
+ sig { params(success_result: Typed::Success).void }
55
55
  def do_something_with_resource(success_result)
56
56
  ...
57
57
  end
58
58
  ```
59
59
 
60
- Finally, there are a few methods you can use on both `T::Result` types.
60
+ Finally, there are a few methods you can use on both `Typed::Result` types.
61
61
 
62
62
  ```ruby
63
63
  result = call_api(1)
@@ -99,16 +99,16 @@ This has several downsides; primarily, this required your caller to _know_ what
99
99
  Railway Oriented Programming, which comes from the functional programming community, alleviates this by _expecting_ the failure states and making them a part of the normal flow of a method. Most errors are recoverable; at the very least we can message them back to the user in some way. We should inform the caller with a Result that could be either a Success or Failure, and allow them continue or take an "off-ramp" with a failure message. If we embrace this style of programming, our `call_api` method turns into this:
100
100
 
101
101
  ```ruby
102
- sig { params(resource_id: Integer).returns(T::Result[Float, String]) }
102
+ sig { params(resource_id: Integer).returns(Typed::Result[Float, String]) }
103
103
  def call_api(resource_id)
104
104
  # something bad happened
105
- return T::Failure.new(error: "I couldn't do it!")
105
+ return Typed::Failure.new(error: "I couldn't do it!")
106
106
 
107
107
  # something other bad thing happened
108
- return T::Failure.new(error: "I couldn't do it for another reason!")
108
+ return Typed::Failure.new(error: "I couldn't do it for another reason!")
109
109
 
110
110
  # Success!
111
- T::Success.new(payload: 1.12)
111
+ Typed::Success.new(payload: 1.12)
112
112
  end
113
113
  ```
114
114
 
data/lib/sorbet-result.rb CHANGED
@@ -4,8 +4,11 @@
4
4
  # frozen_string_literal: true
5
5
 
6
6
  require "sorbet-runtime"
7
- require "t/result"
8
- require "t/nil_payload_error"
9
- require "t/success"
10
- require "t/no_payload_on_failure_error"
11
- require "t/failure"
7
+ require "zeitwerk"
8
+
9
+ # Sorbet-aware namespace to super-charge your projects
10
+ module Typed; end
11
+
12
+ loader = Zeitwerk::Loader.new
13
+ loader.push_dir("#{__dir__}/typed", namespace: Typed)
14
+ loader.setup
@@ -1,11 +1,11 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module T
4
+ module Typed
5
5
  # Represents a failed result. Contains error information but no payload.
6
6
  class Failure < Result
7
- extend Sig
8
- extend Generic
7
+ extend T::Sig
8
+ extend T::Generic
9
9
 
10
10
  Payload = type_member
11
11
  Error = type_member
@@ -19,12 +19,12 @@ module T
19
19
  super()
20
20
  end
21
21
 
22
- sig { override.returns(Boolean) }
22
+ sig { override.returns(T::Boolean) }
23
23
  def success?
24
24
  false
25
25
  end
26
26
 
27
- sig { override.returns(Boolean) }
27
+ sig { override.returns(T::Boolean) }
28
28
  def failure?
29
29
  true
30
30
  end
@@ -1,10 +1,10 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module T
4
+ module Typed
5
5
  # Error when user attempts to unwrap payload for Success Result without payload.
6
6
  class NilPayloadError < StandardError
7
- extend Sig
7
+ extend T::Sig
8
8
 
9
9
  sig { void }
10
10
  def initialize
@@ -1,10 +1,10 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module T
4
+ module Typed
5
5
  # Error when user attempts to access payload from a Failure Result.
6
6
  class NoPayloadOnFailureError < StandardError
7
- extend Sig
7
+ extend T::Sig
8
8
 
9
9
  sig { void }
10
10
  def initialize
@@ -1,22 +1,22 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module T
4
+ module Typed
5
5
  # A monad representing either a success or a failure. Contains payload and error information as well.
6
6
  class Result
7
- extend Sig
8
- extend Helpers
9
- extend Generic
7
+ extend T::Sig
8
+ extend T::Helpers
9
+ extend T::Generic
10
10
 
11
11
  abstract!
12
12
 
13
13
  Payload = type_member
14
14
  Error = type_member
15
15
 
16
- sig { abstract.returns(Boolean) }
16
+ sig { abstract.returns(T::Boolean) }
17
17
  def success?; end
18
18
 
19
- sig { abstract.returns(Boolean) }
19
+ sig { abstract.returns(T::Boolean) }
20
20
  def failure?; end
21
21
 
22
22
  sig { abstract.returns(T.nilable(Payload)) }
@@ -1,11 +1,11 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- module T
4
+ module Typed
5
5
  # Represents a successful result. Contains a payload and no error information.
6
6
  class Success < Result
7
- extend Sig
8
- extend Generic
7
+ extend T::Sig
8
+ extend T::Generic
9
9
 
10
10
  Payload = type_member
11
11
  Error = type_member
@@ -19,12 +19,12 @@ module T
19
19
  super()
20
20
  end
21
21
 
22
- sig { override.returns(Boolean) }
22
+ sig { override.returns(T::Boolean) }
23
23
  def success?
24
24
  true
25
25
  end
26
26
 
27
- sig { override.returns(Boolean) }
27
+ sig { override.returns(T::Boolean) }
28
28
  def failure?
29
29
  false
30
30
  end