README.md in u-service-0.9.0 vs README.md in u-service-0.10.0

- old
+ new

@@ -11,14 +11,15 @@ - [μ-service (Micro::Service)](#%ce%bc-service-microservice) - [Required Ruby version](#required-ruby-version) - [Installation](#installation) - [Usage](#usage) - [How to create a Service Object?](#how-to-create-a-service-object) - - [How to use the Service Object result hooks?](#how-to-use-the-service-object-result-hooks) + - [How to use the result hooks?](#how-to-use-the-result-hooks) - [How to create a pipeline of Service Objects?](#how-to-create-a-pipeline-of-service-objects) - [What is a strict Service Object?](#what-is-a-strict-service-object) - [How to validate Service Object attributes?](#how-to-validate-service-object-attributes) + - [It's possible to compose pipelines with other pipelines?](#its-possible-to-compose-pipelines-with-other-pipelines) - [Development](#development) - [Contributing](#contributing) - [License](#license) - [Code of Conduct](#code-of-conduct) @@ -62,10 +63,11 @@ #====================# # Calling a service # #====================# result = Multiply.call(a: 2, b: 2) + p result.success? # true p result.value # 4 # Note: # The result of a Micro::Service#call @@ -74,24 +76,26 @@ #----------------------------# # Calling a service instance # #----------------------------# result = Multiply.new(a: 2, b: 3).call + p result.success? # true p result.value # 6 #===========================# # Verify the result failure # #===========================# result = Multiply.call(a: '2', b: 2) + p result.success? # false p result.failure? # true p result.value # :invalid_data ``` -### How to use the Service Object result hooks? +### How to use the result hooks? ```ruby class Double < Micro::Service::Base attributes :number @@ -133,59 +137,84 @@ ### How to create a pipeline of Service Objects? ```ruby module Steps class ConvertToNumbers < Micro::Service::Base - attribute :relation + attribute :numbers def call! - if relation.all? { |value| String(value) =~ /\d+/ } - Success(numbers: relation.map(&:to_i)) + if numbers.all? { |value| String(value) =~ /\d+/ } + Success(numbers: numbers.map(&:to_i)) else - Failure('relation must contain only numbers') + Failure('numbers must contain only numeric types') end end end class Add2 < Micro::Service::Strict attribute :numbers def call! - Success(numbers.map { |number| number + 2 }) + Success(numbers: numbers.map { |number| number + 2 }) end end class Double < Micro::Service::Strict attribute :numbers def call! - Success(numbers.map { |number| number * 2 }) + Success(numbers: numbers.map { |number| number * 2 }) end end + + class Square < Micro::Service::Strict + attribute :numbers + + def call! + Success(numbers: numbers.map { |number| number * number }) + end + end end +#=================================================# +# Creating a pipeline using the collection syntax # +#=================================================# + Add2ToAllNumbers = Micro::Service::Pipeline[ Steps::ConvertToNumbers, Steps::Add2 ] -# An alternative way to declare pipelines within classes. +result = Add2ToAllNumbers.call(numbers: %w[1 1 2 2 3 4]) +p result.success? # true +p result.value # {:numbers => [3, 3, 4, 4, 5, 6]} + +#=======================================================# +# An alternative way to create a pipeline using classes # +#=======================================================# + class DoubleAllNumbers include Micro::Service::Pipeline pipeline Steps::ConvertToNumbers, Steps::Double end -result = Add2ToAllNumbers.call(relation: %w[1 1 2 2 3 4]) +DoubleAllNumbers + .call(numbers: %w[1 1 b 2 3 4]) + .on_failure { |message| p message } # "numbers must contain only numeric types" -p result.success? # true -p result.value # [3, 3, 4, 4, 5, 6] +#=================================================================# +# Another way to create a pipeline using the composition operator # +#=================================================================# -DoubleAllNumbers - .call(relation: %w[1 1 b 2 3 4]) - .on_failure { |message| p message } # "relation must contain only numbers" +SquareAllNumbers = + Steps::ConvertToNumbers >> Steps::Square + +SquareAllNumbers + .call(numbers: %w[1 1 2 2 3 4]) + .on_success { |value| p value[:numbers] } # [1, 1, 4, 4, 9, 16] ``` ### What is a strict Service Object? A: Is a service object which will require all keywords (attributes) on its initialization. @@ -246,9 +275,71 @@ # Note: # There is a strict variation for Micro::Service::WithValidation # Use Micro::Service::Strict::Validation if do you want this behavior. ``` + +### It's possible to compose pipelines with other pipelines? + +Answer: Yes + +```ruby +module Steps + class ConvertToNumbers < Micro::Service::Base + attribute :numbers + + def call! + if numbers.all? { |value| String(value) =~ /\d+/ } + Success(numbers: numbers.map(&:to_i)) + else + Failure('numbers must contain only numeric types') + end + end + end + + class Add2 < Micro::Service::Strict + attribute :numbers + + def call! + Success(numbers: numbers.map { |number| number + 2 }) + end + end + + class Double < Micro::Service::Strict + attribute :numbers + + def call! + Success(numbers: numbers.map { |number| number * 2 }) + end + end + + class Square < Micro::Service::Strict + attribute :numbers + + def call! + Success(numbers: numbers.map { |number| number * number }) + end + end +end + +Add2ToAllNumbers = Steps::ConvertToNumbers >> Steps::Add2 +DoubleAllNumbers = Steps::ConvertToNumbers >> Steps::Double +SquareAllNumbers = Steps::ConvertToNumbers >> Steps::Square +DoubleAllNumbersAndAdd2 = DoubleAllNumbers >> Steps::Add2 +SquareAllNumbersAndAdd2 = SquareAllNumbers >> Steps::Add2 +DoubleAllNumbersAndSquareThem = DoubleAllNumbers >> SquareAllNumbersAndAdd2 +SquareAllNumbersAndDoubleThem = SquareAllNumbersAndAdd2 >> DoubleAllNumbers + +DoubleAllNumbersAndSquareThem + .call(numbers: %w[1 1 2 2 3 4]) + .on_success { |value| p value[:numbers] } # [6, 6, 18, 18, 38, 66] + +SquareAllNumbersAndDoubleThem + .call(numbers: %w[1 1 2 2 3 4]) + .on_success { |value| p value[:numbers] } # [6, 6, 12, 12, 22, 36] +``` + +Note: You can blend any of the [syntaxes/approaches to create the pipelines](#how-to-create-a-pipeline-of-service-objects)) - [examples](https://github.com/serradura/u-service/blob/master/test/micro/service/pipeline/blend_test.rb#L7-L34). ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.