Skip to content

Commit

Permalink
Add custom classes support for raise (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
afuno committed Sep 22, 2022
1 parent 7700d0a commit 4b4e4b4
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 17 deletions.
1 change: 1 addition & 0 deletions lib/service_actor/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module ServiceActor::Base
def self.included(base)
# Essential mechanics
base.include(ServiceActor::Core)
base.include(ServiceActor::Raisable)
base.include(ServiceActor::Attributable)
base.include(ServiceActor::Playable)

Expand Down
6 changes: 3 additions & 3 deletions lib/service_actor/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def call(result = nil, **arguments)
# CreateUser.result(name: "Joe")
def result(result = nil, **arguments)
call(result, **arguments)
rescue ServiceActor::Failure => e
rescue failure_class => e
e.result
end
end
Expand Down Expand Up @@ -52,7 +52,7 @@ def _call

# Can be called from inside an actor to stop execution and mark as failed.
def fail!(**arguments)
result.fail!(**arguments)
result.fail!(self.class.failure_class, **arguments)
end

private
Expand All @@ -61,6 +61,6 @@ def fail!(**arguments)
def raise_error_with(message, **arguments)
message = message.call(**arguments) if message.is_a?(Proc)

raise ServiceActor::ArgumentError, message
raise self.class.argument_error_class, message
end
end
2 changes: 1 addition & 1 deletion lib/service_actor/playable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def call

options[:actors].each { |actor| play_actor(actor) }
end
rescue ServiceActor::Failure
rescue self.class.failure_class
rollback
raise
end
Expand Down
20 changes: 20 additions & 0 deletions lib/service_actor/raisable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

module ServiceActor::Raisable
def self.included(base)
base.extend(ClassMethods)
end

module ClassMethods
def inherited(child)
super

child.argument_error_class =
argument_error_class || ServiceActor::ArgumentError

child.failure_class = failure_class || ServiceActor::Failure
end

attr_accessor :argument_error_class, :failure_class
end
end
4 changes: 2 additions & 2 deletions lib/service_actor/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ def inspect
"<#{self.class.name} #{to_h}>"
end

def fail!(result = {})
def fail!(failure_class, result = {})
merge!(result)
merge!(failure?: true)

raise ServiceActor::Failure, self
raise failure_class, self
end

def success?
Expand Down
24 changes: 22 additions & 2 deletions spec/actor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
expect { FailWithError.call }
.to raise_error(ServiceActor::Failure, "Ouch")
end

context "when a custom class is specified" do
it "raises the error message" do
expect { FailWithErrorWithCustomFailureClass.call }
.to raise_error(MyCustomFailure, "Ouch")
end
end
end

context "when an actor updates the context" do
Expand Down Expand Up @@ -258,7 +265,7 @@
context "when called with the wrong type of argument" do
let(:expected_message) do
"The \"name\" input on \"SetNameToDowncase\" must be of " \
"type \"String\" but was \"#{1.class.name}\""
"type \"String\" but was \"Integer\""
end

it "raises" do
Expand Down Expand Up @@ -308,7 +315,7 @@
context "when normal mode" do
let(:expected_message) do
"The \"name\" output on \"SetWrongTypeOfOutput\" must " \
"be of type \"String\" but was \"#{1.class.name}\""
"be of type \"String\" but was \"Integer\""
end

it "raises" do
Expand All @@ -327,6 +334,19 @@
.to raise_error(ServiceActor::ArgumentError, expected_message)
end
end

context "when a custom class is specified" do
let(:expected_message) do
"The \"name\" output on " \
"\"SetWrongTypeOfOutputWithCustomArgumentErrorClass\" must " \
"be of type \"String\" but was \"Integer\""
end

it "raises" do
expect { SetWrongTypeOfOutputWithCustomArgumentErrorClass.call }
.to raise_error(MyCustomArgumentError, expected_message)
end
end
end

context "when using an output called display" do
Expand Down
9 changes: 9 additions & 0 deletions spec/examples/fail_with_error_with_custom_failure_class.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class FailWithErrorWithCustomFailureClass < Actor
self.failure_class = MyCustomFailure

def call
fail!(error: "Ouch", some_other_key: 42)
end
end
3 changes: 3 additions & 0 deletions spec/examples/my_custom_argument_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

class MyCustomArgumentError < ServiceActor::ArgumentError; end
3 changes: 3 additions & 0 deletions spec/examples/my_custom_failure.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

class MyCustomFailure < ServiceActor::Failure; end
9 changes: 0 additions & 9 deletions spec/examples/set_wrong_required_output.rb

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class SetWrongTypeOfOutputWithCustomArgumentErrorClass < Actor
self.argument_error_class = MyCustomArgumentError

output :name, type: String

def call
self.name = 42
end
end

0 comments on commit 4b4e4b4

Please sign in to comment.