diff --git a/CHANGELOG.md b/CHANGELOG.md index ac75aac..e49b1ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Breaking changes: - Invoking undefined methods on `ServiceActor::Result` now raises an error (previously it only issued a warning). (#213) +Feature: +- Make raised exception available as `ServiceActor::Result#exception`. (#220) + ## v5.0.0 Breaking changes: diff --git a/lib/service_actor/failable.rb b/lib/service_actor/failable.rb index 58a2188..6dd4d81 100644 --- a/lib/service_actor/failable.rb +++ b/lib/service_actor/failable.rb @@ -38,7 +38,7 @@ module PrependedMethods def _call super rescue *self.class.fail_ons => e - fail!(error: e.message) + fail!(error: e.message, exception: e) end end end diff --git a/lib/service_actor/result.rb b/lib/service_actor/result.rb index 409e27a..14f3dd0 100644 --- a/lib/service_actor/result.rb +++ b/lib/service_actor/result.rb @@ -62,7 +62,17 @@ def fail!(failure_class = nil, result = {}) data.merge!(result) data[:failure] = true - ::Kernel.raise failure_class, self + cause = data.delete(:exception) + exception = failure_class.new(self) + data[:exception] = exception + + ::Kernel.raise exception unless cause + + begin + ::Kernel.raise cause + rescue + ::Kernel.raise exception + end end def success? @@ -77,6 +87,10 @@ def error data[:error] || nil end + def exception + data[:exception] || nil + end + def merge!(result) data.merge!(result.transform_keys(&:to_sym)) diff --git a/spec/actor_spec.rb b/spec/actor_spec.rb index 3aae709..3c9c806 100644 --- a/spec/actor_spec.rb +++ b/spec/actor_spec.rb @@ -1825,6 +1825,8 @@ def call; end expect(actor.error).to match( /\AThe "name" input on ".+" must be of type "String" but was "Integer"\z/, ) + expect(actor.exception).to be_a ServiceActor::Failure + expect(actor.exception.cause).to be_a ServiceActor::ArgumentError end end diff --git a/spec/service_actor/result_spec.rb b/spec/service_actor/result_spec.rb index 1d5f728..e35669d 100644 --- a/spec/service_actor/result_spec.rb +++ b/spec/service_actor/result_spec.rb @@ -34,6 +34,7 @@ :delete!, :equal?, :error, + :exception, :fail!, :failure?, :hash, @@ -175,6 +176,26 @@ end end + describe "#exception" do + it "returns the raised exception" do + expect { result.fail!(error: "Something went wrong!") } + .to raise_error(ServiceActor::Failure) + exception = result.exception + expect(exception).to be_a ServiceActor::Failure + expect(exception.message).to eq "Something went wrong!" + end + end + + describe "#exception cause" do + it "returns exception passed to fail!" do + cause = ArgumentError.new + expect { result.fail!(exception: cause) } + .to raise_error(ServiceActor::Failure) + expect(result.exception).to be_a ServiceActor::Failure + expect(result.exception.cause).to be cause + end + end + describe "#fail!" do it "merges the hash into the result and marks the result as failed" do expect { result.fail!(name: "Sunny") }