keka 0.1.0 → 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
- SHA1:
3
- metadata.gz: e4644a49e6ff908024e1ec91cdeec0d7a6886c9d
4
- data.tar.gz: 6a89ab5dab98c71ab7f77a1ddfed84419e956eed
2
+ SHA256:
3
+ metadata.gz: 441fd2d2712b2ea5b6a15076088de3a1617945f0683251addd7e0be5f5077b9e
4
+ data.tar.gz: 3d7cf921207b9000a838197669af05d619aadc1252b420d48d74771266dfbccf
5
5
  SHA512:
6
- metadata.gz: b2ba159cfc8a028f3f834cd2b48af5184da28f8b2d85a36ad62711b3771754f812b8f01c60e426f7f39c441eb30c4dc8b7b1eabda0632a970dc94767c13c41c7
7
- data.tar.gz: 62b1c97c626ff58d1e51b033259b9d18bf0c0f71594a73549150f6b6b37aeff5d58944c5d591564fc78ac43975b1ef16bb50725cd3f67d354e2ddb3e17917c9e
6
+ metadata.gz: 447a280a18b005007788861863dce8b2dc647100add773615a1f5e2ae1a1151020f3955b0486da070a8995e32b7c9b168f5da5adf652b8fb8cb535e1e6b1b151
7
+ data.tar.gz: 7514d83dd424338c51254855275b4031d45ba34a4814104130a2549aad7e0676327e288edfb1422b08a899d0528ffc48a93f8822a574f17d6af346a749ab57a3
@@ -0,0 +1,17 @@
1
+ version: 2
2
+ jobs:
3
+ build:
4
+ docker:
5
+ - image: circleci/ruby:2.5.3
6
+ working_directory: ~/repo
7
+ environment:
8
+ BUNDLER_VERSION: 1.17.3
9
+ steps:
10
+ - checkout
11
+ - run: gem install bundler:1.17.3
12
+ - run:
13
+ name: install dependencies
14
+ command: bundle install --jobs=4 --retry=3 --path vendor/bundle
15
+ - run:
16
+ name: run specs
17
+ command: bundle exec rspec
@@ -0,0 +1 @@
1
+ 2.5.3
@@ -0,0 +1,10 @@
1
+ # CHANGELOG
2
+
3
+ ## Unreleased
4
+
5
+ ## Version 0.2.0
6
+ * Support `.rescue_with` to handle exceptions in `.run` block.
7
+ * Add CI.
8
+
9
+ ## Version 0.1.0
10
+ * Initial release.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- keka (0.1.0)
4
+ keka (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -13,19 +13,19 @@ GEM
13
13
  coderay (~> 1.1.0)
14
14
  method_source (~> 0.9.0)
15
15
  rake (10.5.0)
16
- rspec (3.8.0)
17
- rspec-core (~> 3.8.0)
18
- rspec-expectations (~> 3.8.0)
19
- rspec-mocks (~> 3.8.0)
20
- rspec-core (3.8.0)
21
- rspec-support (~> 3.8.0)
22
- rspec-expectations (3.8.2)
16
+ rspec (3.9.0)
17
+ rspec-core (~> 3.9.0)
18
+ rspec-expectations (~> 3.9.0)
19
+ rspec-mocks (~> 3.9.0)
20
+ rspec-core (3.9.1)
21
+ rspec-support (~> 3.9.1)
22
+ rspec-expectations (3.9.0)
23
23
  diff-lcs (>= 1.2.0, < 2.0)
24
- rspec-support (~> 3.8.0)
25
- rspec-mocks (3.8.0)
24
+ rspec-support (~> 3.9.0)
25
+ rspec-mocks (3.9.1)
26
26
  diff-lcs (>= 1.2.0, < 2.0)
27
- rspec-support (~> 3.8.0)
28
- rspec-support (3.8.0)
27
+ rspec-support (~> 3.9.0)
28
+ rspec-support (3.9.2)
29
29
 
30
30
  PLATFORMS
31
31
  ruby
@@ -38,4 +38,4 @@ DEPENDENCIES
38
38
  rspec (~> 3.7)
39
39
 
40
40
  BUNDLED WITH
41
- 1.16.2
41
+ 1.17.3
data/README.md CHANGED
@@ -4,44 +4,34 @@ Keka (Japanese for 'result') is a wrapper that represents the result of a partic
4
4
 
5
5
  ## Installation
6
6
 
7
- Add this line to your application's Gemfile:
8
-
9
7
  ```ruby
10
8
  gem 'keka'
11
9
  ```
12
10
 
13
- And then execute:
14
-
15
- $ bundle
16
-
17
- Or install it yourself as:
18
-
19
- $ gem install keka
20
-
21
11
  ## Usage
22
12
 
23
13
  Below is an example of how the various methods can come together.
24
14
 
25
15
  ```ruby
26
16
  class Order
27
- def refund
17
+ def refund(cancel_delivery = true)
28
18
  Keka.run do
29
19
  # returns an err keka with provided msg if !refundable?
30
20
  Keka.err_unless!(refundable?, 'Payment is no longer refundable.')
31
21
  # returns an err keka with provided msg if !refund!
32
- Keka.err_unless!(refund!, 'Refund failed. Please try again')
22
+ Keka.err_unless!(payment.refund, 'Refund failed. Please try again')
33
23
  # execute statements if nothing 'return' from above
34
24
  do_something_else
35
- # if cancel_delivery?
36
- # => returns an err keka with provided msg if !remove_delivery
37
- Keka.err_unless!(remove_delivery, 'Refunded but failed to remove delivery.') if cancel_delivery?
25
+ # if cancel_delivery
26
+ # => returns an err keka with provided msg if !remove_delivery_assignment
27
+ Keka.err_unless!(remove_delivery_assignment, 'Refunded but failed to remove delivery.') if cancel_delivery
38
28
  # returns an ok keka if nothing 'return' from above
39
29
  end
40
30
  end
41
31
 
42
32
  private
43
33
 
44
- def remove_delivery
34
+ def remove_delivery_assignment
45
35
  Keka.run do
46
36
  # returns an ok keka if already_removed?
47
37
  Keka.ok_if! already_removed?
@@ -64,9 +54,56 @@ class SomeController
64
54
  end
65
55
  ```
66
56
 
67
- Of course, you can also use `.err_unless!`, `err_if!`, and `ok_if!` outside
57
+ Of course, you can also use `.err_unless!`, `.err_if!`, and `.ok_if!` outside
68
58
  of the `Keka.run` block.
69
59
 
60
+ ### Handle Exceptions
61
+
62
+ Before version 0.2.0, handling exceptions in `.run` block is a bit tricky. You might do something like this
63
+
64
+ ```ruby
65
+ def validate_purchase(item_ids)
66
+ Keka.run do
67
+ Item.find(item_ids)
68
+ rescue ActiveRecord::RecordNotFound
69
+ Keka.err_if! true, 'Some item is unavailable'
70
+ end
71
+ end
72
+ ```
73
+
74
+ After version 0.2.0, you can simply
75
+ ```ruby
76
+ # * Returns ok result if no exception is raised.
77
+ # * Returns err result if ActiveRecord::RecordNotFound is raised, with msg set
78
+ # to 'Some item is unavailable'.
79
+ # * Raises if any other non-keka exception is thrown.
80
+ def validate_purchase(item_ids)
81
+ Keka.rescue_with(ActiveRecord::RecordNotFound, 'Some item is unavailable')
82
+ .run { Item.find(item_ids) }
83
+ end
84
+ ```
85
+
86
+ You can also chain `.rescue_with`
87
+ ```ruby
88
+ def validate_purchase(store_id, new_item_payload)
89
+ Keka.rescue_with(ActiveRecord::RecordNotFound, 'Some item is unavailable')
90
+ .rescue_with(ActiveRecord::RecordInvalid, 'Invalid payload')
91
+ .run do
92
+ store = Store.find(store_id)
93
+ store.items.create!(new_item_payload)
94
+ end
95
+ end
96
+ ```
97
+
98
+ Note, by design, `.rescue_with` only rescues from descendants of StandardError. This will **NOT** work.
99
+ ```ruby
100
+ def invalid_example
101
+ # The .rescue_with does NOTHING here. This method will raise a NoMemoryError exception.
102
+ Keka.rescue_with(NoMemoryError, 'oops')
103
+ .run { raise NoMemoryError.new }
104
+ end
105
+ ```
106
+
70
107
  ## Development
71
108
 
72
109
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,72 +1,44 @@
1
1
  require 'keka/version'
2
+ require 'keka/exceptions'
3
+ require 'keka/result'
4
+ require 'keka/context'
2
5
 
3
6
  module Keka
7
+ class << self
8
+ include Context::Originable
4
9
 
5
- class Halt < StandardError
6
- attr_reader :keka
7
- def initialize(keka)
8
- @keka = keka
9
- super
10
+ def err_if!(evaluator, msg = nil)
11
+ raise Halt.new(err(msg)) if (evaluator.respond_to?(:ok?) ? evaluator.ok? : evaluator)
10
12
  end
11
- end
12
-
13
- class Base
14
- attr_accessor :msg
15
13
 
16
- def initialize(is_success, msg)
17
- @is_success = is_success
18
- @msg = msg
14
+ def err_unless!(evaluator, msg = nil)
15
+ if evaluator.is_a? self::Result
16
+ return if evaluator.ok?
17
+ evaluator.msg = msg if msg
18
+ raise Halt.new(evaluator)
19
+ else
20
+ raise Halt.new(err(msg)) unless evaluator
21
+ end
19
22
  end
20
23
 
21
- def ok?
22
- is_success
24
+ def ok_if!(evaluator, msg = nil)
25
+ if evaluator.is_a? self::Result
26
+ return unless evaluator.ok?
27
+ evaluator.msg = msg if msg
28
+ raise Halt.new(evaluator)
29
+ else
30
+ raise Halt.new(ok(msg)) if evaluator
31
+ end
23
32
  end
24
33
 
25
- private
26
- attr_reader :is_success
27
- end
28
-
29
- def self.err_if!(evaluator, msg = nil)
30
- raise Halt.new(err(msg)) if (evaluator.respond_to?(:ok?) ? evaluator.ok? : evaluator)
31
- end
32
-
33
- def self.err_unless!(evaluator, msg = nil)
34
- if evaluator.is_a? self::Base
35
- return if evaluator.ok?
36
- evaluator.msg = msg if msg
37
- raise Halt.new(evaluator)
38
- else
39
- raise Halt.new(err(msg)) unless evaluator
34
+ # private (maybe)
35
+ def ok(msg = nil)
36
+ Result.new(true, msg)
40
37
  end
41
- end
42
38
 
43
- def self.ok_if!(evaluator, msg = nil)
44
- if evaluator.is_a? self::Base
45
- return unless evaluator.ok?
46
- evaluator.msg = msg if msg
47
- raise Halt.new(evaluator)
48
- else
49
- raise Halt.new(ok(msg)) if evaluator
39
+ # private (maybe)
40
+ def err(msg = nil)
41
+ Result.new(false, msg)
50
42
  end
51
43
  end
52
-
53
- def self.run
54
- raise 'Block required!' unless block_given?
55
- yield
56
- ok
57
- rescue Halt => e
58
- e.keka
59
- end
60
-
61
-
62
- # private (maybe)
63
- def self.ok(msg = nil)
64
- Base.new(true, msg)
65
- end
66
-
67
- # private (maybe)
68
- def self.err(msg = nil)
69
- Base.new(false, msg)
70
- end
71
-
72
44
  end
@@ -0,0 +1,43 @@
1
+ module Keka
2
+ class Context
3
+
4
+ module Originable
5
+ def rescue_with(err_class, err_msg = nil)
6
+ Context.new.rescue_with(err_class, err_msg)
7
+ end
8
+
9
+ def run(&block)
10
+ Context.new.run(&block)
11
+ end
12
+ end
13
+
14
+ def initialize
15
+ @opts = {
16
+ rescue_exceptions: []
17
+ }
18
+ end
19
+
20
+ def rescue_with(err_class, err_msg = nil)
21
+ opts[:rescue_exceptions] << {
22
+ klass: err_class,
23
+ msg: err_msg
24
+ }
25
+ self
26
+ end
27
+
28
+ def run
29
+ raise 'Block required!' unless block_given?
30
+ yield
31
+ Keka.ok
32
+ rescue Keka::Halt => e
33
+ e.result
34
+ rescue StandardError => e
35
+ raise unless matched = opts[:rescue_exceptions].detect { |setting| e.is_a?(setting[:klass]) }
36
+ Keka.err(matched[:msg])
37
+ end
38
+
39
+ private
40
+ attr_reader :opts
41
+
42
+ end
43
+ end
@@ -0,0 +1,9 @@
1
+ module Keka
2
+ class Halt < StandardError
3
+ attr_reader :result
4
+ def initialize(result)
5
+ @result = result
6
+ super
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module Keka
2
+ class Result
3
+ attr_accessor :msg
4
+
5
+ def initialize(is_success, msg)
6
+ @is_success = is_success
7
+ @msg = msg
8
+ end
9
+
10
+ def ok?
11
+ is_success
12
+ end
13
+
14
+ private
15
+ attr_reader :is_success
16
+ end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module Keka
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keka
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - zino
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-13 00:00:00.000000000 Z
11
+ date: 2020-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -74,9 +74,11 @@ extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - ".DS_Store"
77
+ - ".circleci/config.yml"
77
78
  - ".gitignore"
78
79
  - ".rspec"
79
- - ".rspec_status"
80
+ - ".ruby-version"
81
+ - CHANGELOG.md
80
82
  - Gemfile
81
83
  - Gemfile.lock
82
84
  - LICENSE.txt
@@ -86,6 +88,9 @@ files:
86
88
  - bin/setup
87
89
  - keka.gemspec
88
90
  - lib/keka.rb
91
+ - lib/keka/context.rb
92
+ - lib/keka/exceptions.rb
93
+ - lib/keka/result.rb
89
94
  - lib/keka/version.rb
90
95
  homepage: https://github.com/zinosama/keka
91
96
  licenses:
@@ -107,8 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
112
  - !ruby/object:Gem::Version
108
113
  version: '0'
109
114
  requirements: []
110
- rubyforge_project:
111
- rubygems_version: 2.6.14
115
+ rubygems_version: 3.0.2
112
116
  signing_key:
113
117
  specification_version: 4
114
118
  summary: Better handle short-circuit logic, result state, and return message