lamy_result 0.2.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 +7 -0
- data/.rspec +5 -0
- data/.rubocop.yml +25 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +55 -0
- data/LICENSE.txt +15 -0
- data/README.md +89 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lamy_result.gemspec +81 -0
- data/lib/lamy_result/lamy.rb +225 -0
- data/lib/lamy_result/version.rb +5 -0
- data/lib/lamy_result.rb +4 -0
- metadata +103 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9de251784cf83e80ac19a2f8d08bd00de25269ccae683b518570bcf710cf5918
|
|
4
|
+
data.tar.gz: 287d464139c3ae445e4cbdf477e9ea4109f08dde36db4394e79f5613fc5be00d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6845ef3a74016eebfdd7c34aa55cca0f4044cf0bdf89fff49f5c31d24393b7165b5e6a648dd08ae5ab17c079d1cbfff8d9a5be31c83693f934a3e6cfcc65141f
|
|
7
|
+
data.tar.gz: 7eb32ea5eb7c3d4da5ff15905fece148885fcdd352d3c06cf4a80e455fd90d88eeacf5212a23fe79c658c3ccd7d787488e609e6a0ab976ba632c134d669ce5a7
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.5
|
|
3
|
+
|
|
4
|
+
Style/StringLiterals:
|
|
5
|
+
Enabled: true
|
|
6
|
+
EnforcedStyle: single_quotes
|
|
7
|
+
|
|
8
|
+
Style/StringLiteralsInInterpolation:
|
|
9
|
+
Enabled: true
|
|
10
|
+
EnforcedStyle: double_quotes
|
|
11
|
+
|
|
12
|
+
Layout/LineLength:
|
|
13
|
+
Max: 79
|
|
14
|
+
|
|
15
|
+
Layout/EndOfLine:
|
|
16
|
+
EnforcedStyle: lf
|
|
17
|
+
|
|
18
|
+
Layout/SpaceInsideBlockBraces:
|
|
19
|
+
SpaceBeforeBlockParameters: false
|
|
20
|
+
|
|
21
|
+
Style/RegexpLiteral:
|
|
22
|
+
EnforcedStyle: slashes
|
|
23
|
+
|
|
24
|
+
Lint/BooleanSymbol:
|
|
25
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [0.2.0] - 2022-03-07
|
|
4
|
+
|
|
5
|
+
### Add
|
|
6
|
+
|
|
7
|
+
- Allow aliases of the status tags to be defined with the .define_status_tags
|
|
8
|
+
method.
|
|
9
|
+
|
|
10
|
+
### Remove
|
|
11
|
+
|
|
12
|
+
- No longer define methods with the method_missing hook.
|
|
13
|
+
|
|
14
|
+
## [0.1.0] - 2022-03-04
|
|
15
|
+
|
|
16
|
+
- Initial release
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
lamy_result (0.2.1)
|
|
5
|
+
|
|
6
|
+
GEM
|
|
7
|
+
remote: https://rubygems.org/
|
|
8
|
+
specs:
|
|
9
|
+
ast (2.4.2)
|
|
10
|
+
diff-lcs (1.5.0)
|
|
11
|
+
parallel (1.21.0)
|
|
12
|
+
parser (3.1.1.0)
|
|
13
|
+
ast (~> 2.4.1)
|
|
14
|
+
rainbow (3.1.1)
|
|
15
|
+
rake (13.0.6)
|
|
16
|
+
regexp_parser (2.2.1)
|
|
17
|
+
rexml (3.2.5)
|
|
18
|
+
rspec (3.11.0)
|
|
19
|
+
rspec-core (~> 3.11.0)
|
|
20
|
+
rspec-expectations (~> 3.11.0)
|
|
21
|
+
rspec-mocks (~> 3.11.0)
|
|
22
|
+
rspec-core (3.11.0)
|
|
23
|
+
rspec-support (~> 3.11.0)
|
|
24
|
+
rspec-expectations (3.11.0)
|
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
26
|
+
rspec-support (~> 3.11.0)
|
|
27
|
+
rspec-mocks (3.11.0)
|
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
29
|
+
rspec-support (~> 3.11.0)
|
|
30
|
+
rspec-support (3.11.0)
|
|
31
|
+
rubocop (1.25.1)
|
|
32
|
+
parallel (~> 1.10)
|
|
33
|
+
parser (>= 3.1.0.0)
|
|
34
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
35
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
36
|
+
rexml
|
|
37
|
+
rubocop-ast (>= 1.15.1, < 2.0)
|
|
38
|
+
ruby-progressbar (~> 1.7)
|
|
39
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
|
40
|
+
rubocop-ast (1.16.0)
|
|
41
|
+
parser (>= 3.1.1.0)
|
|
42
|
+
ruby-progressbar (1.11.0)
|
|
43
|
+
unicode-display_width (2.1.0)
|
|
44
|
+
|
|
45
|
+
PLATFORMS
|
|
46
|
+
x64-mingw32
|
|
47
|
+
|
|
48
|
+
DEPENDENCIES
|
|
49
|
+
lamy_result!
|
|
50
|
+
rake (~> 13.0)
|
|
51
|
+
rspec (~> 3.0)
|
|
52
|
+
rubocop (~> 1.7)
|
|
53
|
+
|
|
54
|
+
BUNDLED WITH
|
|
55
|
+
2.2.27
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Apache License, Version 2.0 (Apache-2.0)
|
|
2
|
+
|
|
3
|
+
Copyright 2022 Jed Burke
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
data/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Lamy Result
|
|
2
|
+
|
|
3
|
+
Lamy Result is a simple utility used to wrap method results with a status and a value.
|
|
4
|
+
|
|
5
|
+
The project is inspired by Elixir and Erlang's tagged tuple and Rust's Result/Option. Despite inspiration from other languages, Lamy Result aims to be idiomatic Ruby and runtime dependency-free.
|
|
6
|
+
|
|
7
|
+
Rather than change the way you're doing things. Returning a single result is great for most cases. You'll know if and when you need something more.
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
include LamyResult
|
|
11
|
+
|
|
12
|
+
result = Lamy.ok('Lamy is awesome')
|
|
13
|
+
|
|
14
|
+
if result.ok?
|
|
15
|
+
do_something_cool result.value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# or
|
|
19
|
+
|
|
20
|
+
# Will only evaluate if the status is :ok
|
|
21
|
+
result.ok_then do |v|
|
|
22
|
+
do_something_cool v
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
result.to_a
|
|
26
|
+
# Output: [:ok, 'Lamy is awesome']
|
|
27
|
+
|
|
28
|
+
result.to_h
|
|
29
|
+
# Output: { status: :ok, value: 'Lamy is awesome' }
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# Aliases allow for natural expression.
|
|
33
|
+
|
|
34
|
+
def do_another_cool_thing
|
|
35
|
+
# Report success
|
|
36
|
+
Lamy.success('It worked')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
another_result = do_another_cool_thing
|
|
40
|
+
|
|
41
|
+
# As in "Was the operation successful?"
|
|
42
|
+
another_result.successful?
|
|
43
|
+
|
|
44
|
+
# As in "Has the operation succeeded?"
|
|
45
|
+
another_result.succeeded?
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
Add this line to your application's Gemfile:
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
gem 'lamy_result'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
And then execute:
|
|
57
|
+
|
|
58
|
+
$ bundle install
|
|
59
|
+
|
|
60
|
+
Or install it yourself as:
|
|
61
|
+
|
|
62
|
+
$ gem install lamy_result
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
A few pre-designed status labels are included: `success` `ok` `failed` `error` `true` `false`
|
|
67
|
+
|
|
68
|
+
As a short-hand way to create a result, each one corresponds to a static method (or class method) on the Lamy class.
|
|
69
|
+
|
|
70
|
+
For example, `Lamy.failed('You did not think this through.')` will instantize a Lamy instance with the status set to `:failed` and the value to `You did not think this through.`
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## Motivation
|
|
74
|
+
|
|
75
|
+
The idea came from a function which would check if a file exists with either dashes or underscores. If I was looking for `./ecchi/ecchi-pic-7.jpg`, it should also check for `./ecchi/ecchi_pic_7.jpg`. Without going on a tangent, the function is meant to reconcile file name inconsistencies.
|
|
76
|
+
|
|
77
|
+
The return value could be the file name if it exists and false if does not. Returning a hash with `status` and `value` was more appealing. And that's where we are now.
|
|
78
|
+
|
|
79
|
+
## Name?
|
|
80
|
+
|
|
81
|
+
Named after the hololive VTuber Yukihana Lamy. I was watching her content while designing the class. Thought that maybe naming it in honor of her would give me the motivation to deliver a documented and tested production-ready gem. It's now more complicated than initially intended. So maybe it wasn't a good idea.
|
|
82
|
+
|
|
83
|
+
## Contributing
|
|
84
|
+
|
|
85
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/JedBurke/LamyResult.
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
The gem is available as open source under the terms of the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0).
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
require 'lamy'
|
|
6
|
+
|
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
+
|
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
11
|
+
# require "pry"
|
|
12
|
+
# Pry.start
|
|
13
|
+
|
|
14
|
+
require 'irb'
|
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lamy_result.gemspec
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/lamy_result/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lamy_result'
|
|
7
|
+
spec.version = LamyResult::VERSION
|
|
8
|
+
spec.authors = ['Jed Burke']
|
|
9
|
+
spec.email = ['opensource@evrnetwork.co.za']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Wrap results with a status and a value.'
|
|
12
|
+
spec.description = <<~EOF
|
|
13
|
+
The project is inspired by Elixir and Erlang's tagged tuple and Rust's Result/Option. Despite inspiration from other languages, Lamy Result aims to be idiomatic Ruby and runtime dependency-free.
|
|
14
|
+
|
|
15
|
+
Rather than change the way you're doing things. Returning a single result is great for most cases. You'll know if and when you need something more.
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
include LamyResult
|
|
19
|
+
|
|
20
|
+
result = Lamy.ok('Lamy is awesome')
|
|
21
|
+
|
|
22
|
+
if result.ok?
|
|
23
|
+
do_something_cool result.value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# or
|
|
27
|
+
|
|
28
|
+
# Will only evaluate if the status is :ok
|
|
29
|
+
result.ok_then do |v|
|
|
30
|
+
do_something_cool v
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
result.to_a
|
|
34
|
+
# Output: [:ok, 'Lamy is awesome']
|
|
35
|
+
|
|
36
|
+
result.to_h
|
|
37
|
+
# Output: { status: :ok, value: 'Lamy is awesome' }
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Aliases allow for natural expression.
|
|
41
|
+
|
|
42
|
+
def do_another_cool_thing
|
|
43
|
+
# Report success
|
|
44
|
+
Lamy.success('It worked')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
another_result = do_another_cool_thing
|
|
48
|
+
|
|
49
|
+
# As in "Was the operation successful?"
|
|
50
|
+
another_result.successful?
|
|
51
|
+
|
|
52
|
+
# As in "Has the operation succeeded?"
|
|
53
|
+
another_result.succeeded?
|
|
54
|
+
```
|
|
55
|
+
EOF
|
|
56
|
+
|
|
57
|
+
spec.homepage = 'https://evrnetwork.co.za'
|
|
58
|
+
spec.license = 'Apache-2.0'
|
|
59
|
+
spec.required_ruby_version = ">= 2.5.0"
|
|
60
|
+
|
|
61
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
62
|
+
spec.metadata['source_code_uri'] = 'https://github.com/JedBurke/LamyResult'
|
|
63
|
+
spec.metadata['changelog_uri'] = 'https://github.com/JedBurke/LamyResult/blob/master/CHANGELOG.md'
|
|
64
|
+
|
|
65
|
+
# Specify which files should be added to the gem when it is released.
|
|
66
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
67
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
68
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
69
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
spec.bindir = "exe"
|
|
73
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
74
|
+
spec.require_paths = ["lib"]
|
|
75
|
+
|
|
76
|
+
# Uncomment to register a new dependency of your gem
|
|
77
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
|
78
|
+
|
|
79
|
+
# For more information and examples about making a new gem, checkout our
|
|
80
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
|
81
|
+
end
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LamyResult
|
|
4
|
+
|
|
5
|
+
# Creates and checks result instances.
|
|
6
|
+
#
|
|
7
|
+
# A quick reference for class and instance methods.
|
|
8
|
+
# Lamy.ok is a class method to be called on the `Lamy` class.
|
|
9
|
+
#
|
|
10
|
+
# Lamy#ok? is an instance method called on a Lamy instance, which is
|
|
11
|
+
# returned by Lamy.ok.
|
|
12
|
+
# result = Lamy.ok(Excon.get('https://example.com'))
|
|
13
|
+
# result.ok? => true
|
|
14
|
+
#
|
|
15
|
+
# See .define_status_tags for the method defined at runtime.
|
|
16
|
+
class Lamy
|
|
17
|
+
def initialize(status:, value: nil)
|
|
18
|
+
@status = status
|
|
19
|
+
.to_s
|
|
20
|
+
.downcase
|
|
21
|
+
.to_sym
|
|
22
|
+
|
|
23
|
+
@value = value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The raw attributes may be accessed from outside the class, but
|
|
27
|
+
# shouldn't be changed once set.
|
|
28
|
+
attr_reader :status,
|
|
29
|
+
:value
|
|
30
|
+
|
|
31
|
+
# Compares the current instance's status to the input value. This is a
|
|
32
|
+
# lov-level method meant to be used by the #ok? and #success? methods.
|
|
33
|
+
def status_is?(value)
|
|
34
|
+
@status == value.to_sym
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Calls #status_is? on the `status_to_check` and if true, yields the value.
|
|
38
|
+
# Otherwise, returns the instance. This is a low-level method meant to be
|
|
39
|
+
# used by #ok_then and #success_then methods.
|
|
40
|
+
def assert_status_then(status_to_check:)
|
|
41
|
+
if status_is?(status_to_check)
|
|
42
|
+
return yield @value if block_given?
|
|
43
|
+
|
|
44
|
+
return @value
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
self
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Returns the status attribute as a symbol or a TrueClass/FalseClass. This
|
|
51
|
+
# is a low-level method meant to be used by #to_a and #to_h.
|
|
52
|
+
def export_status
|
|
53
|
+
# If the status is a boolean, return the status as a boolean.
|
|
54
|
+
# Otherwise, return it as a symbol, which it should already be.
|
|
55
|
+
if true? || false?
|
|
56
|
+
@status.to_s.to_sym == true.to_s.to_sym
|
|
57
|
+
else
|
|
58
|
+
@status.to_s.to_sym
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Returns an array of the instance. The status instance attribute is
|
|
63
|
+
# first and the value attribute is second. The status will be returned
|
|
64
|
+
# as a symbol unless it is true or false. At which point, it will
|
|
65
|
+
# be converted.
|
|
66
|
+
def to_a
|
|
67
|
+
[
|
|
68
|
+
export_status,
|
|
69
|
+
@value
|
|
70
|
+
]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Returns a hash of the instance with @status under the `status` key
|
|
74
|
+
# and @value under the `value` key. The status will be returned as a
|
|
75
|
+
# symbol unless it is true or false. At which point, it will be converted.
|
|
76
|
+
def to_h
|
|
77
|
+
{
|
|
78
|
+
status: export_status,
|
|
79
|
+
value: @value
|
|
80
|
+
}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Adds one or more new status tags to be used by the
|
|
84
|
+
def self.define_status_tags(*status_tags)
|
|
85
|
+
# Use Array() over [] to create an array if status_tags is not an array,
|
|
86
|
+
# but not create an array within an array.
|
|
87
|
+
Array(
|
|
88
|
+
status_tags
|
|
89
|
+
).each do |status|
|
|
90
|
+
new_status, *new_status_aliases = Array(status)
|
|
91
|
+
|
|
92
|
+
# Defines the short-hand class method like .ok(input)
|
|
93
|
+
self.define_status_method(new_status, *new_status_aliases)
|
|
94
|
+
|
|
95
|
+
# Define status check instance methods like #ok?
|
|
96
|
+
self.define_status_check_method(new_status, *new_status_aliases)
|
|
97
|
+
|
|
98
|
+
# Define conditional instance methods like #ok_then
|
|
99
|
+
self.define_conditional_then_method(new_status, *new_status_aliases)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.format_status_check_method(status)
|
|
104
|
+
"#{status.to_s}?".to_sym
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def self.format_conditional_method(status)
|
|
108
|
+
"#{status.to_s}_then".to_sym
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.define_status_method(status, *aliases)
|
|
112
|
+
self
|
|
113
|
+
.class
|
|
114
|
+
.send(:define_method, status) do |value|
|
|
115
|
+
Lamy.new(status: status, value: value)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Define aliases for the new status if we got any.
|
|
119
|
+
define_class_aliases_for(status, *aliases)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Defines an instance method to check the status label. E.g. #ok?
|
|
123
|
+
def self.define_status_check_method(status, *aliases)
|
|
124
|
+
method_symbol = format_status_check_method(status)
|
|
125
|
+
status_check_aliases = aliases.map do |s|
|
|
126
|
+
format_status_check_method(s)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
define_method(method_symbol) do
|
|
130
|
+
# Get the status that we need to check. It should have
|
|
131
|
+
# been captured.
|
|
132
|
+
status_is?(status.to_sym)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
assert_new_instance_method! method_symbol
|
|
136
|
+
|
|
137
|
+
self.define_instance_aliases_for(method_symbol, *status_check_aliases)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def self.define_conditional_then_method(status, *aliases)
|
|
141
|
+
method_symbol = format_conditional_method(status)
|
|
142
|
+
status_conditional_aliases = aliases.map do |s|
|
|
143
|
+
format_conditional_method(s)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
define_method(method_symbol) do |&method_block|
|
|
147
|
+
assert_status_then(status_to_check: status, &method_block)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
assert_new_instance_method! method_symbol
|
|
151
|
+
|
|
152
|
+
define_instance_aliases_for(
|
|
153
|
+
method_symbol,
|
|
154
|
+
*status_conditional_aliases
|
|
155
|
+
)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Checks if the method is an instance method, otherwise raises a
|
|
159
|
+
# StandardError.
|
|
160
|
+
def self.assert_new_instance_method!(method_symbol)
|
|
161
|
+
unless self.instance_methods.include?(method_symbol)
|
|
162
|
+
raise StandardError.new "##{method_symbol} is not an instance method."
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
true
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Defines a class or instance alias for the supplied method with each of
|
|
169
|
+
# the supplied array items.
|
|
170
|
+
def self.define_aliases_for(
|
|
171
|
+
method_symbol,
|
|
172
|
+
instance_alias,
|
|
173
|
+
*method_aliases
|
|
174
|
+
)
|
|
175
|
+
method_aliases.each do |method_alias|
|
|
176
|
+
if instance_alias
|
|
177
|
+
alias_method(method_alias, method_symbol)
|
|
178
|
+
else
|
|
179
|
+
self.class.alias_method(method_alias, method_symbol)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
true
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def self.define_class_aliases_for(method_symbol, *method_aliases)
|
|
187
|
+
define_aliases_for(method_symbol, false, *method_aliases)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Defines an instance alias for the supplied method with each of
|
|
191
|
+
# the supplied array items.
|
|
192
|
+
def self.define_instance_aliases_for(method_symbol, *method_aliases)
|
|
193
|
+
define_aliases_for(
|
|
194
|
+
method_symbol,
|
|
195
|
+
true,
|
|
196
|
+
*method_aliases
|
|
197
|
+
)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Override the equality operators and set them as aliases for
|
|
201
|
+
# the #status_is? method.
|
|
202
|
+
alias == status_is?
|
|
203
|
+
alias eql? status_is?
|
|
204
|
+
|
|
205
|
+
class << self
|
|
206
|
+
# The singular form may be more comfortable for users wanting to define
|
|
207
|
+
# a single tag.
|
|
208
|
+
alias define_status_tag define_status_tags
|
|
209
|
+
|
|
210
|
+
# `add_status_tags` might be more comfortable or easier to remember than
|
|
211
|
+
# `define_status_tags`
|
|
212
|
+
alias add_status_tags define_status_tags
|
|
213
|
+
alias add_status_tag define_status_tags
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Add the basic tags to the class.
|
|
217
|
+
Lamy.define_status_tags(
|
|
218
|
+
[:succeeded, :success, :successful],
|
|
219
|
+
[:failed, :fail, :error],
|
|
220
|
+
:ok,
|
|
221
|
+
:true,
|
|
222
|
+
:false
|
|
223
|
+
)
|
|
224
|
+
end
|
|
225
|
+
end
|
data/lib/lamy_result.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lamy_result
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jed Burke
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2022-04-10 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: |
|
|
14
|
+
The project is inspired by Elixir and Erlang's tagged tuple and Rust's Result/Option. Despite inspiration from other languages, Lamy Result aims to be idiomatic Ruby and runtime dependency-free.
|
|
15
|
+
|
|
16
|
+
Rather than change the way you're doing things. Returning a single result is great for most cases. You'll know if and when you need something more.
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
include LamyResult
|
|
20
|
+
|
|
21
|
+
result = Lamy.ok('Lamy is awesome')
|
|
22
|
+
|
|
23
|
+
if result.ok?
|
|
24
|
+
do_something_cool result.value
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# or
|
|
28
|
+
|
|
29
|
+
# Will only evaluate if the status is :ok
|
|
30
|
+
result.ok_then do |v|
|
|
31
|
+
do_something_cool v
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
result.to_a
|
|
35
|
+
# Output: [:ok, 'Lamy is awesome']
|
|
36
|
+
|
|
37
|
+
result.to_h
|
|
38
|
+
# Output: { status: :ok, value: 'Lamy is awesome' }
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Aliases allow for natural expression.
|
|
42
|
+
|
|
43
|
+
def do_another_cool_thing
|
|
44
|
+
# Report success
|
|
45
|
+
Lamy.success('It worked')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
another_result = do_another_cool_thing
|
|
49
|
+
|
|
50
|
+
# As in "Was the operation successful?"
|
|
51
|
+
another_result.successful?
|
|
52
|
+
|
|
53
|
+
# As in "Has the operation succeeded?"
|
|
54
|
+
another_result.succeeded?
|
|
55
|
+
```
|
|
56
|
+
email:
|
|
57
|
+
- opensource@evrnetwork.co.za
|
|
58
|
+
executables: []
|
|
59
|
+
extensions: []
|
|
60
|
+
extra_rdoc_files: []
|
|
61
|
+
files:
|
|
62
|
+
- ".rspec"
|
|
63
|
+
- ".rubocop.yml"
|
|
64
|
+
- CHANGELOG.md
|
|
65
|
+
- Gemfile
|
|
66
|
+
- Gemfile.lock
|
|
67
|
+
- LICENSE.txt
|
|
68
|
+
- README.md
|
|
69
|
+
- Rakefile
|
|
70
|
+
- bin/console
|
|
71
|
+
- bin/setup
|
|
72
|
+
- lamy_result.gemspec
|
|
73
|
+
- lib/lamy_result.rb
|
|
74
|
+
- lib/lamy_result/lamy.rb
|
|
75
|
+
- lib/lamy_result/version.rb
|
|
76
|
+
homepage: https://evrnetwork.co.za
|
|
77
|
+
licenses:
|
|
78
|
+
- Apache-2.0
|
|
79
|
+
metadata:
|
|
80
|
+
homepage_uri: https://evrnetwork.co.za
|
|
81
|
+
source_code_uri: https://github.com/JedBurke/LamyResult
|
|
82
|
+
changelog_uri: https://github.com/JedBurke/LamyResult/blob/master/CHANGELOG.md
|
|
83
|
+
post_install_message:
|
|
84
|
+
rdoc_options: []
|
|
85
|
+
require_paths:
|
|
86
|
+
- lib
|
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
88
|
+
requirements:
|
|
89
|
+
- - ">="
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
version: 2.5.0
|
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
requirements: []
|
|
98
|
+
rubyforge_project:
|
|
99
|
+
rubygems_version: 2.7.3
|
|
100
|
+
signing_key:
|
|
101
|
+
specification_version: 4
|
|
102
|
+
summary: Wrap results with a status and a value.
|
|
103
|
+
test_files: []
|