to-result 0.0.2 → 0.0.4

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: 0bf957670d51788e15be5797daeb430d409cc38967e9f3ba93027ce66eefe93c
4
- data.tar.gz: 5500df2709d9dd14780e53858cf6a2a10fe029d90d3c097e11280104983fdf44
3
+ metadata.gz: 6db91d218609e2e2694dbc1ef6754d8e7c9951d27b8bb73ad521c856db4b9c75
4
+ data.tar.gz: 90f313139ed88c00b1c1877c4d8c94d3629d2d1662fee8315a64e65894ea81d4
5
5
  SHA512:
6
- metadata.gz: 80580831a173303c62330c741bccaa6bb6edad1155ef9639e33c4e1076132cff165b0a7a9d6d91d2a9d472a69841c3f6fd7af9ab177edcbc6488e8d34d958c14
7
- data.tar.gz: 92eda88e706fbe5b330a5417190904d158487e469c726e64d07380e334efb07b9f30def99a2e6f19fa3e354d184cd9892287d18f02dbffe2130cadf5f351abf4
6
+ metadata.gz: 4113a67772569963f5b8c4f9711168903aab0a16daddf4d00a2fb1ef288651989b46b64a07e8d4b97fd8ab83e3df716c9f2cd850fb8eecb350ae30ad68359fac
7
+ data.tar.gz: 0604e31717e86753ff06df3bda5754b11916bb27b5f5b8b0b22a3d2ad73a98d3269ba4f0da3ba81c73247161815118a22e580ac6f69538555788e091052fd335
data/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+ ## [0.0.4](https://github.com/a-chris/to-result/tree/0.0.4) (2022-10-08)
3
+
4
+ - Adds a global `configuration` object for ToResult
5
+ - Adds `on_error` field in `configuration` to execute a block every time a error is catched
6
+
7
+ [Full Changelog](https://github.com/a-chris/to-result/compare/0.0.3...0.0.4)
8
+
9
+ ## [0.0.3](https://github.com/a-chris/to-result/tree/0.0.3) (2022-10-08)
10
+
11
+ - Fixed file name, `require 'to_result'` is not needed anymore to make this gem work.
12
+
13
+ [Full Changelog](https://github.com/a-chris/to-result/compare/0.0.2...0.0.3)
14
+
15
+ ## [0.0.2](https://github.com/a-chris/to-result/tree/0.0.2) (2022-09-18)
16
+
17
+ [Full Changelog](https://github.com/a-chris/to-result/compare/0.0.1...0.0.2)
18
+
19
+ ## [0.0.1](https://github.com/a-chris/to-result/tree/0.0.1) (2022-09-18)
20
+
21
+ [Full Changelog](https://github.com/a-chris/to-result/compare/8dce552d6d07a2a145c45dbf7d05dbe6b0c5c578...0.0.1)
22
+
23
+
24
+
25
+ \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in pulsarcli.gemspec
6
+ gemspec
7
+
8
+ gem 'dry-monads', '~> 1.4'
9
+
10
+ gem 'byebug', '~> 11.1'
11
+
12
+ gem 'minitest', '~> 5.16'
13
+
14
+ gem 'mocha', '~> 1.15'
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ to-result (0.0.4)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ byebug (11.1.3)
10
+ concurrent-ruby (1.1.10)
11
+ dry-core (0.8.1)
12
+ concurrent-ruby (~> 1.0)
13
+ dry-monads (1.4.0)
14
+ concurrent-ruby (~> 1.0)
15
+ dry-core (~> 0.7)
16
+ minitest (5.16.3)
17
+ mocha (1.15.0)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ byebug (~> 11.1)
24
+ dry-monads (~> 1.4)
25
+ minitest (~> 5.16)
26
+ mocha (~> 1.15)
27
+ to-result!
28
+
29
+ BUNDLED WITH
30
+ 2.3.15
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Christian
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,134 @@
1
+
2
+ # ToResult
3
+
4
+ ToResult is a wrapper built over `dry-monads` to make the `Do Notation`, `Result` and `Try` concepts more handy and consistent to use, in particular to implement the **Railway Pattern**.
5
+
6
+ ## Why I created ToResult
7
+
8
+ `dry-monads` is full of edge cases that require to write boilerplate code everytime I want a method to return a `Success` or `Failure`, for example:
9
+
10
+ ```ruby
11
+ def my_method
12
+ Success(another_method.call)
13
+ rescue StandardError => e
14
+ Failure(e)
15
+ end
16
+ ```
17
+
18
+ so I started using `Try`, that makes the code easier to read and faster to write:
19
+ ```ruby
20
+ def my_method
21
+ Try do
22
+ another_method.call
23
+ end.to_result
24
+ end
25
+ ```
26
+
27
+ but I feel like `to_result` is not really visible at the end of the code and if you forget to write it (as always happens to me) your application blows up.
28
+
29
+ But this is not the bigget problem, bear with me.
30
+
31
+ One of the biggest problem is that we cannot use the `Do Notation` inside a `Try` block:
32
+ ```ruby
33
+ # this will return a Failure(Dry::Monads::Do::Halt)
34
+ def my_method
35
+ Try do
36
+ yield Failure('error code')
37
+ end.to_result
38
+ end
39
+ ```
40
+
41
+ and you cannot even use `yield` and `rescue` in the same method:
42
+
43
+ ```ruby
44
+ # this will return a Failure(Dry::Monads::Do::Halt)
45
+ def my_method
46
+ yield Failure('error code')
47
+ rescue StandardError => e
48
+ # e is an instance of Dry::Monads::Do::Halt
49
+ Failure(e)
50
+ end
51
+ ```
52
+
53
+ because they will raise a `Dry::Monads::Do::Halt` exception and the original exception will be forever lost if we do not "unbox" the exception with `e.result`.
54
+
55
+ ## Installation
56
+
57
+ To install with bundler:
58
+ ```bash
59
+ bundle add to-result
60
+ ```
61
+ or with `gem`:
62
+ ```bash
63
+ gem install to-result
64
+ ```
65
+
66
+ ## Usage
67
+
68
+ To use it with instances of a class, just include it
69
+ ```ruby
70
+ require 'to_result'
71
+
72
+ class MyClass
73
+ include ToResultMixin
74
+
75
+ def my_method
76
+ ToResult do
77
+ whatever_method.call
78
+ end
79
+ end
80
+ end
81
+ ```
82
+
83
+ or if you want to use it with Singleton Classes:
84
+ ```ruby
85
+ require 'to_result'
86
+
87
+ class MyClass
88
+ extend ToResultMixin
89
+
90
+ class << self
91
+ def my_method
92
+ ToResult do
93
+ whatever_method.call
94
+ end
95
+ end
96
+ end
97
+ end
98
+ ```
99
+
100
+ now you can always use `ToResult` all the time you wanted to use `Success`, `Failure` or `Try` but with a more convenient interface and consistent behaviour.
101
+
102
+ Look at this:
103
+
104
+ ```ruby
105
+ ToResult { raise StandardError.new('error code') }
106
+ # returns Failure(StandardError('error code'))
107
+
108
+ ToResult { yield Success('hello!') }
109
+ # returns Success('hello!')
110
+
111
+ ToResult { yield Failure('error code') }
112
+ # returns Failure('error code')
113
+
114
+ ToResult { yield Failure(StandardError.new('error code')) }
115
+ # returns Failure(StandardError('error code'))
116
+
117
+ ToResult([YourCustomError]) { yield Failure(YourCustomError.new('error code')) }
118
+ # returns Failure(YourCustomError('error code'))
119
+
120
+ ToResult([ArgumentError]) { yield Failure(YourCustomError.new('error code')) }
121
+ # raises YourCustomError('error code')
122
+ ```
123
+
124
+ ## Roadmap
125
+ I'm already planning to implement some useful features:
126
+ - [x] write more examples/documentation/tests
127
+ - [ ] configurable error logging when an exception is catched inside `DoResult`
128
+ e.g. sending the log to Airbrake or whathever service you are using
129
+ - [ ] transform/process the catched error
130
+ - [ ] any other suggestion would be appreciated 😁
131
+
132
+ ## Authors
133
+
134
+ - [@a-chris](https://www.github.com/a-chris)
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 'to-result'
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__)
@@ -3,6 +3,19 @@ require 'dry/monads'
3
3
  module ToResultMixin
4
4
  include Dry::Monads[:do, :result, :try]
5
5
 
6
+ class Configuration
7
+ attr_accessor :on_error
8
+ end
9
+
10
+ @@configuration = Configuration.new
11
+
12
+ #
13
+ # Allow to override the @@configuration fields
14
+ #
15
+ def self.configure
16
+ yield @@configuration
17
+ end
18
+
6
19
  #
7
20
  # ToResult executes a block of code and returns Success or Failure.
8
21
  # All exceptions inherited from StandardError are catched and
@@ -20,8 +33,11 @@ module ToResultMixin
20
33
  Proc.new do
21
34
  f.call
22
35
  rescue Dry::Monads::Do::Halt => e
23
- return e.result
36
+ error = e.result
37
+ @@configuration.on_error.call(error) if @@configuration.on_error.respond_to?(:call)
38
+ return error
24
39
  rescue *exceptions => e
40
+ @@configuration.on_error.call(e) if @@configuration.on_error.respond_to?(:call)
25
41
  raise e
26
42
  end
27
43
  ).to_result
@@ -0,0 +1,5 @@
1
+ class FakeLogger
2
+ def self.log_error
3
+ true
4
+ end
5
+ end
@@ -0,0 +1,73 @@
1
+ require 'minitest/autorun'
2
+ require 'mocha/minitest'
3
+ require 'byebug'
4
+
5
+ require './lib/to-result'
6
+ require './tests/support/fake_logger'
7
+
8
+ class ToResultTest < Minitest::Test
9
+ include ToResultMixin
10
+
11
+ def setup
12
+ super
13
+ @value = 'hello world!'
14
+ end
15
+
16
+ def teardown
17
+ super
18
+
19
+ # reset the configuration after each test
20
+ ToResultMixin.configure { |c| c = {} }
21
+ end
22
+
23
+ def test_string
24
+ assert ToResult { @value } == Success(@value)
25
+ end
26
+
27
+ def test_success
28
+ expected = Success(@value)
29
+ assert ToResult { expected } == Success(expected)
30
+ end
31
+
32
+ def test_exception
33
+ expected = StandardError.new(@value)
34
+ assert ToResult { raise expected } == Failure(expected)
35
+ end
36
+
37
+ def test_exception_included_in_exceptions_list
38
+ expected = ArgumentError.new(@value)
39
+ assert ToResult([ArgumentError]) { raise expected } == Failure(expected)
40
+ end
41
+
42
+ def test_exception_not_included_in_exceptions_list
43
+ expected = NameError.new(@value)
44
+ assert_raises(NameError) { ToResult([ArgumentError]) { raise expected } }
45
+ end
46
+
47
+ def test_yield_failure
48
+ expected = Failure(@value)
49
+ # this will raise a Dry::Monads::Do::Halt exception
50
+ assert ToResult { yield expected } == expected
51
+ end
52
+
53
+ def test_yield_failure_exception
54
+ expected = Failure(StandardError.new(@value))
55
+ # this will raise a Dry::Monads::Do::Halt exception
56
+ assert ToResult { yield expected } == expected
57
+ end
58
+
59
+ def test_on_error
60
+ FakeLogger.expects(:log_error).once
61
+
62
+ # creating a clean room just for testing purpose
63
+ clean_room = Class.new(Object)
64
+ clean_room.new.instance_eval do
65
+ ToResultMixin.configure do |c|
66
+ c.on_error = Proc.new { FakeLogger.log_error }
67
+ end
68
+ end
69
+
70
+ expected = StandardError.new(@value)
71
+ assert ToResult { raise expected } == Failure(expected)
72
+ end
73
+ end
data/to-result.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'to-result'
8
+ s.version = '0.0.4'
9
+ s.summary = 'A wrapper over dry-monads to offer a handy and consistent way to implement the Railway pattern.'
10
+ s.description = 'A wrapper over dry-monads to offer a handy and consistent way to implement the Railway pattern.'
11
+ s.authors = ['Christian Toscano']
12
+ s.homepage = 'https://github.com/a-chris/to-result'
13
+ s.license = 'MIT'
14
+
15
+ s.require_paths = ['lib']
16
+ s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR).reject { |f| (f == '.gitignore') || f =~ /^examples/ }
17
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: to-result
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Toscano
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-18 00:00:00.000000000 Z
11
+ date: 2022-10-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A wrapper over dry-monads to offer a handy and consistent way to implement
14
14
  the Railway pattern.
@@ -17,7 +17,16 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
- - lib/to_result.rb
20
+ - CHANGELOG.md
21
+ - Gemfile
22
+ - Gemfile.lock
23
+ - LICENSE
24
+ - README.md
25
+ - bin/console
26
+ - lib/to-result.rb
27
+ - tests/support/fake_logger.rb
28
+ - tests/to_result_test.rb
29
+ - to-result.gemspec
21
30
  homepage: https://github.com/a-chris/to-result
22
31
  licenses:
23
32
  - MIT