diff --git a/README.md b/README.md index 806416df..87c997c7 100644 --- a/README.md +++ b/README.md @@ -108,11 +108,11 @@ class Multiply < Micro::Case # 2. Define the method `call!` with its business logic def call! - # 3. Wrap the use case result/output using the `Success()` or `Failure()` methods + # 3. Wrap the use case result/output using the `Success(result: *)` or `Failure(result: *)` methods if a.is_a?(Numeric) && b.is_a?(Numeric) - Success(a * b) + Success result: { number: a * b } else - Failure { '`a` and `b` attributes must be numeric' } + Failure result: { message: '`a` and `b` attributes must be numeric' } end end end @@ -126,14 +126,14 @@ end result = Multiply.call(a: 2, b: 2) result.success? # true -result.value # 4 +result.data # { number: 4 } # Failure result bad_result = Multiply.call(a: 2, b: '2') bad_result.failure? # true -bad_result.value # "`a` and `b` attributes must be numeric" +bad_result.data # { message: "`a` and `b` attributes must be numeric" } #-----------------------------# # Calling a use case instance # @@ -141,7 +141,7 @@ bad_result.value # "`a` and `b` attributes must be numeric" result = Multiply.new(a: 2, b: 3).call -result.value # 6 +result.value # { number: 6 } # Note: # ---- @@ -156,11 +156,13 @@ result.value # 6 A `Micro::Case::Result` stores the use cases output data. These are their main methods: - `#success?` returns true if is a successful result. - `#failure?` returns true if is an unsuccessful result. -- `#value` the result value itself. +- `#data` the result data itself. - `#type` a Symbol which gives meaning for the result, this is useful to declare different types of failures or success. -- `#on_success` or `#on_failure` are hook methods that help you define the application flow. +- `#on_success` or `#on_failure` are hook methods that help you to define the application flow. - `#use_case` if is a failure result, the use case responsible for it will be accessible through this method. This feature is handy to handle a flow failure (this topic will be covered ahead). -- `#then` allows if the current result is a success, the `then` method will allow to applying a new use case for its value. +- `#then` this method will allow applying a new use case if the current result was a success. The idea of this feature is to allow the creation of dynamic flows. + +> **Note:** for backward compatibility, you could use the `#value` method as an alias of `#data` method. [⬆️ Back to Top](#table-of-contents-) @@ -175,9 +177,13 @@ class Divide < Micro::Case attributes :a, :b def call! - invalid_attributes.empty? ? Success(a / b) : Failure(invalid_attributes) - rescue => e - Failure(e) + if invalid_attributes.empty? + Success result: { number: a / b } + else + Failure result: { invalid_attributes: invalid_attributes } + end + rescue => exception + Failure result: exception end private def invalid_attributes @@ -190,7 +196,7 @@ end result = Divide.call(a: 2, b: 2) result.type # :ok -result.value # 1 +result.data # { number: 1 } result.success? # true result.use_case # raises `Micro::Case::Error::InvalidAccessToTheUseCaseObject: only a failure result can access its own use case` @@ -199,7 +205,7 @@ result.use_case # raises `Micro::Case::Error::InvalidAccessToTheUseCaseObject: o bad_result = Divide.call(a: 2, b: '2') bad_result.type # :error -bad_result.value # {"b"=>"2"} +bad_result.data # { invalid_attributes: { "b"=>"2" } } bad_result.failure? # true bad_result.use_case # #2, "b"=>"2"}, @a=2, @b="2", @__result=#, @type=:error, @value={"b"=>"2"}, @success=false> @@ -208,31 +214,33 @@ bad_result.use_case # #2, "b"=>"2"}, @a=2, @b err_result = Divide.call(a: 2, b: 0) err_result.type # :exception -err_result.value # +err_result.data # { exception: } err_result.failure? # true err_result.use_case # #2, "b"=>0}, @a=2, @b=0, @__result=#, @type=:exception, @value=#, @success=false> # Note: # ---- # Any Exception instance which is wrapped by -# the Failure() method will receive `:exception` instead of the `:error` type. +# the Failure(result: *) method will receive `:exception` instead of the `:error` type. ``` [⬆️ Back to Top](#table-of-contents-) #### How to define custom result types? -Answer: Use a symbol as the argument of `Success()`, `Failure()` methods and declare a block to set their values. +Answer: Use a symbol as the argument of `Success()`, `Failure()` methods and declare the `result:` keyword to set the result data. ```ruby class Multiply < Micro::Case attributes :a, :b def call! - return Success(a * b) if a.is_a?(Numeric) && b.is_a?(Numeric) - - Failure(:invalid_data) do - attributes.reject { |_, input| input.is_a?(Numeric) } + if a.is_a?(Numeric) && b.is_a?(Numeric) + Success result: { number: a * b } + else + Failure :invalid_data, result: { + attributes: attributes.reject { |_, input| input.is_a?(Numeric) } + } end end end @@ -242,7 +250,7 @@ end result = Multiply.call(a: 3, b: 2) result.type # :ok -result.value # 6 +result.data # { number: 6 } result.success? # true # Failure result @@ -250,7 +258,7 @@ result.success? # true bad_result = Multiply.call(a: 3, b: '2') bad_result.type # :invalid_data -bad_result.value # {"b"=>"2"} +bad_result.data # { attributes: {"b"=>"2"} } bad_result.failure? # true ``` @@ -258,23 +266,25 @@ bad_result.failure? # true #### Is it possible to define a custom result type without a block? -Answer: Yes, it is. But only for failure results! +Answer: Yes, it is possible. But this will have special behavior because the result data will be a hash with the given type as the key and true as its value. ```ruby class Multiply < Micro::Case attributes :a, :b def call! - return Failure(:invalid_data) unless a.is_a?(Numeric) && b.is_a?(Numeric) - - Success(a * b) + if a.is_a?(Numeric) && b.is_a?(Numeric) + Success result: { number: a * b } + else + Failure(:invalid_data) + end end end result = Multiply.call(a: 2, b: '2') result.failure? # true -result.value # :invalid_data +result.data # { :invalid_data => true } result.type # :invalid_data result.use_case.attributes # {"a"=>2, "b"=>"2"}