call_sheet 0.2.0 → 0.3.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
  SHA1:
3
- metadata.gz: 96d48219b6b93de88c46f9bdd0e146a1d7874fc7
4
- data.tar.gz: d8f8982248cab8b53578356484b0a933aaab5a92
3
+ metadata.gz: bb1702c17a58664dd0fe67c3e785151da951b418
4
+ data.tar.gz: 9fe07911b83cd2b03f46e4067423322bb61a1cd4
5
5
  SHA512:
6
- metadata.gz: 460c3efef5e4b95ab44bb4a6b105c022e60fd57b0830f8c6ecbbdbaca20b29698a51e2389104823381785dba3893af85f57f29b0621d622690cab0d3d694ca93
7
- data.tar.gz: ab53c4c441ab6c0b58baaff91b8a8ba188bf190d5b12355922f51719d86ec9c565660df927f5b34f2011da3972dfd4c12a1bcb37ed43ee193e8d965415fdba52
6
+ metadata.gz: ed94e027073aec6f2ca2d7a3a7e5323463caab088536266fe55b1b41c0bc0b88db1b277cd60f7e5ebbd7799a06965aca1dc250276f3fd91fd57858f60f80b93e
7
+ data.tar.gz: 37253ade71ab026981f3064d9bc2a77ac5a64fe3cb870096fa01c6bba6c871796cd19a4e0f5d71d69f36695c02a884be027c9c7870dd3d8847c709d0e501c442
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source "https://rubygems.org"
2
2
 
3
3
  # Gem dependencies are specified in call_sheet.gemspec
4
4
  gemspec
5
+
6
+ gem "kleisli"
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- call_sheet (0.1.0)
4
+ call_sheet (0.2.0)
5
5
  deterministic (>= 0.15.3)
6
+ kleisli
6
7
  wisper (>= 1.6.0)
7
8
 
8
9
  GEM
@@ -15,6 +16,7 @@ GEM
15
16
  diff-lcs (1.2.5)
16
17
  docile (1.1.5)
17
18
  json (1.8.3)
19
+ kleisli (0.2.6)
18
20
  parser (2.2.3.0)
19
21
  ast (>= 1.1, < 3.0)
20
22
  powerpack (0.1.1)
@@ -54,6 +56,7 @@ PLATFORMS
54
56
  DEPENDENCIES
55
57
  bundler (~> 1.10)
56
58
  call_sheet!
59
+ kleisli
57
60
  rake (~> 10.4.2)
58
61
  rspec (~> 3.3.0)
59
62
  rubocop (~> 0.34.2)
data/README.md CHANGED
@@ -25,7 +25,7 @@ Call Sheet is based on the following ideas, drawn mostly from [Transflow](http:/
25
25
 
26
26
  Requiring a business transaction's steps to exist as independent operations directly addressable voa a container means that they can be tested in isolation and easily reused throughout your application. Following from this, keeping the business transaction to a series of high-level, declarative steps ensures that it's easy to understand at a glance.
27
27
 
28
- The output of each step is wrapped in a [Deterministic](https://github.com/pzol/deterministic) `Result` object (either `Success(s)` or `Failure(f)`). This allows the steps to be chained together and ensures that processing stops in the case of a failure. Returning a `Result` from the overall transaction also allows for error handling to remain a primary concern without it getting in the way of tidy, straightforward operation logic. Wrapping the step output also means that you can work with a wide variety of operations within your application – they don’t need to return a `Result` already.
28
+ The output of each step is wrapped in a [Kleisli](https://github.com/txus/kleisli) `Either` object (`Right` for success or `Left` for failure). This allows the steps to be chained together and ensures that processing stops in the case of a failure. Returning an `Either` from the overall transaction also allows for error handling to remain a primary concern without it getting in the way of tidy, straightforward operation logic. Wrapping the step output also means that you can work with a wide variety of operations within your application – they don’t need to return an `Either` already.
29
29
 
30
30
  ## Usage
31
31
 
@@ -33,10 +33,10 @@ All you need to use Call Sheet is a container of operations that respond to `#ca
33
33
 
34
34
  Each operation is integrated into your business transaction through one of the following step adapters:
35
35
 
36
- * `map` – any output is considered successful and returned as `Success(output)`
37
- * `try` – the operation may raise an exception in an error case. This is caught and returned as `Failure(exception)`. The output is otherwise returned as `Success(output)`.
38
- * `tee` – the operation interacts with some external system and has no meaningful output. The original input is passed through and returned as `Success(input)`.
39
- * `raw` or `step` – the operation already returns its own `Result` object, and needs no special handling.
36
+ * `map` – any output is considered successful and returned as `Right(output)`
37
+ * `try` – the operation may raise an exception in an error case. This is caught and returned as `Left(exception)`. The output is otherwise returned as `Right(output)`.
38
+ * `tee` – the operation interacts with some external system and has no meaningful output. The original input is passed through and returned as `Right(input)`.
39
+ * `raw` or `step` – the operation already returns its own `Either` object, and needs no special handling.
40
40
 
41
41
  ```ruby
42
42
  DB = []
@@ -54,31 +54,33 @@ save_user = CallSheet(container: container) do
54
54
  end
55
55
 
56
56
  save_user.call("name" => "Jane", "email" => "jane@doe.com")
57
- # => Success({:name=>"Jane", :email=>"jane@doe.com"})
57
+ # => Right({:name=>"Jane", :email=>"jane@doe.com"})
58
58
 
59
59
  DB
60
60
  # => [{:name=>"Jane", :email=>"jane@doe.com"}]
61
61
  ```
62
62
 
63
- Each transaction returns a `Success(s)` or `Failure(f)` result. You can handle these different results with Deterministic’s [pattern matching](https://github.com/pzol/deterministic#pattern-matching):
63
+ Each transaction returns a result value wrapped in a `Left` or `Right` object. You can handle these different results (including errors arising from particular steps) with a match block:
64
64
 
65
65
  ```ruby
66
- save_user.call(name: "Jane", email: "jane@doe.com").match do
67
- Success(s) do
66
+ save_user.call(name: "Jane", email: "jane@doe.com") do |m|
67
+ m.success do
68
68
  puts "Succeeded!"
69
69
  end
70
- Failure(f, where { f == :validate }) do |errors|
71
- # In a more realistic example, you’d loop through a list of messages in `errors`.
72
- puts "Couldn’t save this user. Please provide an email address."
73
- end
74
- Failure(f) do
75
- puts "Couldn’t save this user."
70
+
71
+ m.failure do |f|
72
+ f.on :validate do |errors|
73
+ # In a more realistic example, you’d loop through a list of messages in `errors`.
74
+ puts "Couldn’t save this user. Please provide an email address."
75
+ end
76
+
77
+ f.otherwise do |error|
78
+ puts "Couldn’t save this user."
79
+ end
76
80
  end
77
81
  end
78
82
  ```
79
83
 
80
- You can use guard expressions like `where { f == :step_name }` in the failure matches to catch failures that arise from particular steps in your transaction.
81
-
82
84
  ### Passing additional step arguments
83
85
 
84
86
  Additional arguments for step operations can be passed at the time of calling your transaction. Provide these arguments as an array, and they’ll be [splatted](https://endofline.wordpress.com/2011/01/21/the-strange-ruby-splat/) into the front of the operation’s arguments. This means that transactions can effectively support operations with any sort of `#call(*args, input)` interface.
@@ -100,10 +102,10 @@ end
100
102
 
101
103
  input = {"name" => "Jane", "email" => "jane@doe.com"}
102
104
  save_user.call(input, validate: ["doe.com"])
103
- # => Success({:name=>"Jane", :email=>"jane@doe.com"})
105
+ # => Right({:name=>"Jane", :email=>"jane@doe.com"})
104
106
 
105
107
  save_user.call(input, validate: ["smith.com"])
106
- # => Failure("not allowed")
108
+ # => Left("not allowed")
107
109
  ```
108
110
 
109
111
  ### Subscribing to step notifications
@@ -149,7 +151,7 @@ save_user = CallSheet(container: large_whole_app_container) do
149
151
  end
150
152
  ```
151
153
 
152
- A `raw` step can also be used if the operation in your container already returns a `Result` and therefore doesn’t need any special handling.
154
+ A `raw` step (also aliased as `step`) can be used if the operation in your container already returns an `Either` and therefore doesn’t need any special handling.
153
155
 
154
156
  ## Installation
155
157
 
@@ -169,7 +171,7 @@ Bug reports and pull requests are welcome on [GitHub](http://github.com/icelab/c
169
171
 
170
172
  Call Sheet is developed and maintained by [Icelab](http://icelab.com.au/).
171
173
 
172
- Call Sheet’s error handling is based on Scott Wlaschin’s [Railway Oriented Programming](http://fsharpforfunandprofit.com/rop/), found via Zohaib Rauf’s [Railway Oriented Programming in Elixir](http://zohaib.me/railway-programming-pattern-in-elixir/) blog post. Call Sheet’s behavior as a business transaction library draws heavy inspiration from Piotr Solnica’s [Transflow](http://github.com/solnic/transflow) and Gilbert B Garza’s [Solid Use Case](https://github.com/mindeavor/solid_use_case). Piotr Zolnierek’s [Deterministic](https://github.com/pzol/deterministic) gem makes working with functional programming patterns in Ruby fun and easy. Thank you all!
174
+ Call Sheet’s error handling is based on Scott Wlaschin’s [Railway Oriented Programming](http://fsharpforfunandprofit.com/rop/), found via Zohaib Rauf’s [Railway Oriented Programming in Elixir](http://zohaib.me/railway-programming-pattern-in-elixir/) blog post. Call Sheet’s behavior as a business transaction library draws heavy inspiration from Piotr Solnica’s [Transflow](http://github.com/solnic/transflow) and Gilbert B Garza’s [Solid Use Case](https://github.com/mindeavor/solid_use_case). Josep M. Bach’s [Kleisli](https://github.com/txus/kleisli) gem makes functional programming patterns in Ruby accessible and fun. Thank you all!
173
175
 
174
176
  ## License
175
177
 
@@ -9,8 +9,6 @@ require "call_sheet/transaction"
9
9
 
10
10
  module CallSheet
11
11
  class DSL
12
- include Deterministic::Prelude::Result
13
-
14
12
  # @api private
15
13
  attr_reader :options
16
14
 
@@ -0,0 +1,40 @@
1
+ module CallSheet
2
+ class ResultMatcher
3
+ attr_reader :result
4
+ attr_reader :value
5
+
6
+ def initialize(result)
7
+ @result = result
8
+ @value = result.value
9
+ end
10
+
11
+ def success(&block)
12
+ block.call value if result.is_a?(Kleisli::Either::Right)
13
+ end
14
+
15
+ def failure(&block)
16
+ block.call FailureMatcher.new(result) if result.is_a?(Kleisli::Either::Left)
17
+ end
18
+
19
+ class FailureMatcher
20
+ attr_reader :result
21
+ attr_reader :value
22
+
23
+ def initialize(result)
24
+ @result = result
25
+ @value = result.value
26
+ end
27
+
28
+ def on(step_name, &block)
29
+ if value.__step_name == step_name
30
+ @matched = true
31
+ block.call value
32
+ end
33
+ end
34
+
35
+ def otherwise(&block)
36
+ block.call value unless @matched
37
+ end
38
+ end
39
+ end
40
+ end
@@ -4,7 +4,6 @@ require "call_sheet/step_failure"
4
4
  module CallSheet
5
5
  # @api private
6
6
  class Step
7
- include Deterministic::Prelude::Result
8
7
  include Wisper::Publisher
9
8
 
10
9
  attr_reader :step_name
@@ -22,15 +21,15 @@ module CallSheet
22
21
  end
23
22
 
24
23
  def call(input)
25
- args = (call_args << input)
24
+ args = (call_args.dup << input)
26
25
  result = operation.call(*args)
27
26
 
28
- result.map { |value|
27
+ result.fmap { |value|
29
28
  broadcast :"#{step_name}_success", value
30
- Success(value)
31
- }.map_err { |value|
29
+ value
30
+ }.or { |value|
32
31
  broadcast :"#{step_name}_failure", *args, value
33
- Failure(StepFailure.new(step_name, value))
32
+ Left(StepFailure.new(step_name, value))
34
33
  }
35
34
  end
36
35
 
@@ -2,8 +2,6 @@ module CallSheet
2
2
  module StepAdapters
3
3
  # @api private
4
4
  class Base
5
- include Deterministic::Prelude::Result
6
-
7
5
  attr_reader :operation
8
6
  attr_reader :options
9
7
 
@@ -3,7 +3,7 @@ module CallSheet
3
3
  # @api private
4
4
  class Map < Base
5
5
  def call(*args, input)
6
- Success(operation.call(input, *args))
6
+ Right(operation.call(input, *args))
7
7
  end
8
8
  end
9
9
 
@@ -4,7 +4,7 @@ module CallSheet
4
4
  class Tee < Base
5
5
  def call(*args, input)
6
6
  operation.call(*args, input)
7
- Success(input)
7
+ Right(input)
8
8
  end
9
9
  end
10
10
 
@@ -8,9 +8,9 @@ module CallSheet
8
8
  end
9
9
 
10
10
  def call(*args, input)
11
- Success(operation.call(*args, input))
11
+ Right(operation.call(*args, input))
12
12
  rescue *Array(options[:catch]) => e
13
- Failure(e)
13
+ Left(e)
14
14
  end
15
15
  end
16
16
 
@@ -1,5 +1,7 @@
1
1
  module CallSheet
2
2
  class StepFailure < BasicObject
3
+ attr_reader :__step_name
4
+
3
5
  def initialize(step_name, object)
4
6
  @__step_name = step_name
5
7
  @__object = object
@@ -10,7 +12,7 @@ module CallSheet
10
12
  end
11
13
 
12
14
  def ==(other)
13
- @__step_name == other || @__object == other
15
+ @__object == other
14
16
  end
15
17
  end
16
18
  end
@@ -1,7 +1,7 @@
1
+ require "call_sheet/result_matcher"
2
+
1
3
  module CallSheet
2
4
  class Transaction
3
- include Deterministic::Prelude::Result
4
-
5
5
  # @api private
6
6
  attr_reader :steps
7
7
  private :steps
@@ -12,12 +12,15 @@ module CallSheet
12
12
  end
13
13
 
14
14
  # @api public
15
- def call(input, options = {})
15
+ def call(input, options = {}, &block)
16
16
  assert_valid_options(options)
17
17
  assert_options_satisfy_step_arity(options)
18
18
 
19
19
  steps = steps_with_options_applied(options)
20
- steps.inject(Success(input), :>>)
20
+ result = steps.inject(Right(input), :>>)
21
+
22
+ block.call ResultMatcher.new(result) if block
23
+ result
21
24
  end
22
25
  alias_method :[], :call
23
26
 
@@ -1,4 +1,4 @@
1
1
  # Business transaction DSL.
2
2
  module CallSheet
3
- VERSION = "0.2.0".freeze
3
+ VERSION = "0.3.0".freeze
4
4
  end
data/lib/call_sheet.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "deterministic"
1
+ require "kleisli"
2
2
  require "call_sheet/version"
3
3
  require "call_sheet/dsl"
4
4
 
data/spec/examples.txt CHANGED
@@ -1,21 +1,23 @@
1
1
  example_id | status | run_time |
2
2
  -------------------------------------------------------- | ------ | --------------- |
3
- ./spec/integration/call_sheet_spec.rb[1:1:1] | passed | 0.00244 seconds |
4
- ./spec/integration/call_sheet_spec.rb[1:1:2] | passed | 0.00114 seconds |
5
- ./spec/integration/call_sheet_spec.rb[1:1:3] | passed | 0.00101 seconds |
6
- ./spec/integration/call_sheet_spec.rb[1:1:4] | passed | 0.00237 seconds |
7
- ./spec/integration/call_sheet_spec.rb[1:2:1] | passed | 0.0008 seconds |
8
- ./spec/integration/call_sheet_spec.rb[1:2:2] | passed | 0.00086 seconds |
9
- ./spec/integration/call_sheet_spec.rb[1:2:3] | passed | 0.00154 seconds |
10
- ./spec/integration/call_sheet_spec.rb[1:2:4] | passed | 0.00087 seconds |
11
- ./spec/integration/call_sheet_spec.rb[1:2:5] | passed | 0.00085 seconds |
12
- ./spec/integration/call_sheet_spec.rb[1:3:1] | passed | 0.00068 seconds |
13
- ./spec/integration/call_sheet_spec.rb[1:3:2] | passed | 0.00072 seconds |
14
- ./spec/integration/call_sheet_spec.rb[1:3:3] | passed | 0.00065 seconds |
15
- ./spec/integration/passing_step_arguments_spec.rb[1:1:1] | passed | 0.00312 seconds |
16
- ./spec/integration/passing_step_arguments_spec.rb[1:2:1] | passed | 0.00023 seconds |
17
- ./spec/integration/passing_step_arguments_spec.rb[1:3:1] | passed | 0.00202 seconds |
18
- ./spec/integration/publishing_step_events_spec.rb[1:1:1] | passed | 0.00096 seconds |
19
- ./spec/integration/publishing_step_events_spec.rb[1:1:2] | passed | 0.00077 seconds |
20
- ./spec/integration/publishing_step_events_spec.rb[1:2:1] | passed | 0.00254 seconds |
21
- ./spec/integration/publishing_step_events_spec.rb[1:2:2] | passed | 0.00083 seconds |
3
+ ./spec/integration/call_sheet_spec.rb[1:1:1] | passed | 0.00147 seconds |
4
+ ./spec/integration/call_sheet_spec.rb[1:1:2] | passed | 0.00103 seconds |
5
+ ./spec/integration/call_sheet_spec.rb[1:1:3] | passed | 0.00032 seconds |
6
+ ./spec/integration/call_sheet_spec.rb[1:1:4] | passed | 0.00108 seconds |
7
+ ./spec/integration/call_sheet_spec.rb[1:1:5] | passed | 0.00043 seconds |
8
+ ./spec/integration/call_sheet_spec.rb[1:2:1] | passed | 0.00224 seconds |
9
+ ./spec/integration/call_sheet_spec.rb[1:2:2] | passed | 0.00028 seconds |
10
+ ./spec/integration/call_sheet_spec.rb[1:2:3] | passed | 0.0007 seconds |
11
+ ./spec/integration/call_sheet_spec.rb[1:2:4] | passed | 0.00027 seconds |
12
+ ./spec/integration/call_sheet_spec.rb[1:2:5] | passed | 0.00025 seconds |
13
+ ./spec/integration/call_sheet_spec.rb[1:2:6] | passed | 0.00048 seconds |
14
+ ./spec/integration/call_sheet_spec.rb[1:3:1] | passed | 0.00035 seconds |
15
+ ./spec/integration/call_sheet_spec.rb[1:3:2] | passed | 0.00018 seconds |
16
+ ./spec/integration/call_sheet_spec.rb[1:3:3] | passed | 0.0003 seconds |
17
+ ./spec/integration/passing_step_arguments_spec.rb[1:1:1] | passed | 0.00023 seconds |
18
+ ./spec/integration/passing_step_arguments_spec.rb[1:2:1] | passed | 0.00039 seconds |
19
+ ./spec/integration/passing_step_arguments_spec.rb[1:3:1] | passed | 0.00137 seconds |
20
+ ./spec/integration/publishing_step_events_spec.rb[1:1:1] | passed | 0.00055 seconds |
21
+ ./spec/integration/publishing_step_events_spec.rb[1:1:2] | passed | 0.00052 seconds |
22
+ ./spec/integration/publishing_step_events_spec.rb[1:2:1] | passed | 0.0004 seconds |
23
+ ./spec/integration/publishing_step_events_spec.rb[1:2:2] | passed | 0.0016 seconds |
@@ -1,6 +1,4 @@
1
1
  RSpec.describe CallSheet do
2
- include Deterministic::Prelude::Result
3
-
4
2
  let(:call_sheet) {
5
3
  CallSheet(container: container) do
6
4
  map :process
@@ -13,7 +11,7 @@ RSpec.describe CallSheet do
13
11
  let(:container) {
14
12
  {
15
13
  process: -> input { {name: input["name"], email: input["email"]} },
16
- verify: -> input { Success(input) },
14
+ verify: -> input { Right(input) },
17
15
  validate: -> input { input[:email].nil? ? raise(Test::NotValidError, "email required") : input },
18
16
  persist: -> input { Test::DB << input and true }
19
17
  }
@@ -26,87 +24,120 @@ RSpec.describe CallSheet do
26
24
 
27
25
  context "successful" do
28
26
  let(:input) { {"name" => "Jane", "email" => "jane@doe.com"} }
29
- let(:run_call_sheet) { call_sheet.call(input) }
30
27
 
31
28
  it "calls the operations" do
32
- run_call_sheet
29
+ call_sheet.call(input)
33
30
  expect(Test::DB).to include(name: "Jane", email: "jane@doe.com")
34
31
  end
35
32
 
36
33
  it "returns a success" do
37
- expect(run_call_sheet).to be_success
34
+ expect(call_sheet.call(input)).to be_a Kleisli::Either::Right
38
35
  end
39
36
 
40
37
  it "wraps the result of the final operation" do
41
- expect(run_call_sheet.value).to eq(name: "Jane", email: "jane@doe.com")
38
+ expect(call_sheet.call(input).value).to eq(name: "Jane", email: "jane@doe.com")
39
+ end
40
+
41
+ it "can be called multiple times to the same effect" do
42
+ call_sheet.call(input)
43
+ call_sheet.call(input)
44
+
45
+ expect(Test::DB[0]).to eq(name: "Jane", email: "jane@doe.com")
46
+ expect(Test::DB[1]).to eq(name: "Jane", email: "jane@doe.com")
42
47
  end
43
48
 
44
- it "supports pattern matching on success" do
45
- match = run_call_sheet.match do
46
- Success(s) { "Matched on success" }
47
- Failure(_) {}
49
+ it "supports matching on success" do
50
+ results = []
51
+
52
+ call_sheet.call(input) do |m|
53
+ m.success do |value|
54
+ results << "success for #{value[:email]}"
55
+ end
48
56
  end
49
57
 
50
- expect(match).to eq "Matched on success"
58
+ expect(results.first).to eq "success for jane@doe.com"
51
59
  end
52
60
  end
53
61
 
54
62
  context "failed in a try step" do
55
63
  let(:input) { {"name" => "Jane"} }
56
- let(:run_call_sheet) { call_sheet.call(input) }
57
64
 
58
65
  it "does not run subsequent operations" do
59
- run_call_sheet
66
+ call_sheet.call(input)
60
67
  expect(Test::DB).to be_empty
61
68
  end
62
69
 
63
70
  it "returns a failure" do
64
- expect(run_call_sheet).to be_failure
71
+ expect(call_sheet.call(input)).to be_a Kleisli::Either::Left
65
72
  end
66
73
 
67
74
  it "wraps the result of the failing operation" do
68
- expect(run_call_sheet.value).to be_a Test::NotValidError
75
+ expect(call_sheet.call(input).value).to be_a Test::NotValidError
69
76
  end
70
77
 
71
- it "supports pattern matching on failure" do
72
- match = run_call_sheet.match do
73
- Success(_) {}
74
- Failure(f) { "Matched on failure" }
78
+ it "supports matching on failure" do
79
+ results = []
80
+
81
+ call_sheet.call(input) do |m|
82
+ m.failure do |f|
83
+ results << "Failed: #{f.value}"
84
+ end
75
85
  end
76
86
 
77
- expect(match).to eq "Matched on failure"
87
+ expect(results.first).to eq "Failed: email required"
78
88
  end
79
89
 
80
- it "supports pattern matching on specific step failures" do
81
- match = run_call_sheet.match do
82
- Success(_) {}
83
- Failure(f, where { f == :validate }) { "Matched validate failure" }
84
- Failure(_) {}
90
+ it "supports matching on specific step failures" do
91
+ results = []
92
+
93
+ call_sheet.call(input) do |m|
94
+ m.failure do |f|
95
+ f.on :validate do |v|
96
+ results << "Validation failure: #{v}"
97
+ end
98
+ end
99
+ end
100
+
101
+ expect(results.first).to eq "Validation failure: email required"
102
+ end
103
+
104
+ it "supports matching on un-named step failures" do
105
+ results = []
106
+
107
+ call_sheet.call(input) do |m|
108
+ m.failure do |f|
109
+ f.on :some_other_step do |v|
110
+ results << "Some other step failure"
111
+ end
112
+
113
+ f.otherwise do |v|
114
+ results << "Catch-all failure: #{v}"
115
+ end
116
+ end
85
117
  end
86
118
 
87
- expect(match).to eq "Matched validate failure"
119
+ expect(results.first).to eq "Catch-all failure: email required"
88
120
  end
89
121
  end
90
122
 
91
123
  context "failed in a raw step" do
92
124
  let(:input) { {"name" => "Jane", "email" => "jane@doe.com"} }
93
- let(:run_call_sheet) { call_sheet.call(input) }
94
125
 
95
126
  before do
96
- container[:verify] = -> input { Failure("raw failure") }
127
+ container[:verify] = -> input { Left("raw failure") }
97
128
  end
98
129
 
99
130
  it "does not run subsequent operations" do
100
- run_call_sheet
131
+ call_sheet.call(input)
101
132
  expect(Test::DB).to be_empty
102
133
  end
103
134
 
104
135
  it "returns a failure" do
105
- expect(run_call_sheet).to be_failure
136
+ expect(call_sheet.call(input)).to be_a Kleisli::Either::Left
106
137
  end
107
138
 
108
139
  it "returns the failing value from the operation" do
109
- expect(run_call_sheet.value).to eq "raw failure"
140
+ expect(call_sheet.call(input).value).to eq "raw failure"
110
141
  end
111
142
  end
112
143
  end
@@ -28,7 +28,7 @@ RSpec.describe "Passing additional arguments to step operations" do
28
28
  let(:step_options) { {validate: ["doe.com"]} }
29
29
 
30
30
  it "passes the arguments and calls the operations successfully" do
31
- expect(run_call_sheet).to be_success
31
+ expect(run_call_sheet).to be_a Kleisli::Either::Right
32
32
  end
33
33
  end
34
34
 
@@ -1,6 +1,4 @@
1
1
  RSpec.describe "publishing step events" do
2
- include Deterministic::Prelude::Result
3
-
4
2
  let(:call_sheet) {
5
3
  CallSheet(container: container) do
6
4
  map :process
@@ -12,7 +10,7 @@ RSpec.describe "publishing step events" do
12
10
  let(:container) {
13
11
  {
14
12
  process: -> input { {name: input["name"]} },
15
- verify: -> input { input[:name].to_s != "" ? Success(input) : Failure("no name") },
13
+ verify: -> input { input[:name].to_s != "" ? Right(input) : Left("no name") },
16
14
  persist: -> input { Test::DB << input and true }
17
15
  }
18
16
  }
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require "simplecov"
2
- SimpleCov.start
3
2
  SimpleCov.minimum_coverage 100
3
+ SimpleCov.start do
4
+ add_filter "/spec/"
5
+ end
4
6
 
5
7
  require "call_sheet"
6
8
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: call_sheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Riley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-02 00:00:00.000000000 Z
11
+ date: 2015-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deterministic
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.15.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: kleisli
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: wisper
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +150,7 @@ files:
136
150
  - Rakefile
137
151
  - lib/call_sheet.rb
138
152
  - lib/call_sheet/dsl.rb
153
+ - lib/call_sheet/result_matcher.rb
139
154
  - lib/call_sheet/step.rb
140
155
  - lib/call_sheet/step_adapters.rb
141
156
  - lib/call_sheet/step_adapters/base.rb