u-service 0.13.0 → 0.13.1

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
  SHA256:
3
- metadata.gz: f637ed45a67693473bf30661b6a4822f1d6ea15246d46b24df3051546781a16b
4
- data.tar.gz: ec7c4d4c8052ff1f293b9323bdb447505880dd658a1d0e6219dd2233a40a2b1a
3
+ metadata.gz: b93d4099f9d4f7646b94241bb5b66190635dff1a56781c7aa152fb458acce958
4
+ data.tar.gz: bf4a7a017a8fbc891904a74ffa80b8aaaadc577cfcfd178e062ed42410dfec9a
5
5
  SHA512:
6
- metadata.gz: 5339646f0ce88b4842c9f8d0425ddb16c5edacb81f97dea46eb695da625a2b142fb24a15bf7256f16952f5fb45526c0d812ab8e7a54ac045ce49959ff5a1b637
7
- data.tar.gz: 1927b9f7da2f9a5ca5ea369c768173485ff704e3fb8142eccaa612484e6c83a9aeba7589c11f61d573ed7a0b341ba437003f5e9e57bb74eb76ef5789fde84169
6
+ metadata.gz: 7d69adaf4e77a2707904a31a29ffd51abc866a27cdd210039b24c5def4ce9fbbbb0dec88e0b39bbfe6e855692d2a186c0931de6225d0269de6b972f048de936e
7
+ data.tar.gz: eb3812b5a44fa8742560eee26e49fd987f6bb4a5fb30e35aafa6a0b6d870c4a96b62a9a1af5b5387c7a58b8e97d45e739b64b4768d95bdd53c3784fa4df879f2
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  module Service
5
- VERSION = '0.13.0'.freeze
5
+ VERSION = '0.13.1'.freeze
6
6
  end
7
7
  end
data/u-service.gemspec CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
  # Specify which files should be added to the gem when it is released.
30
30
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
31
31
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
32
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|assets|benchmarks|comparisons|examples)/}) }
33
33
  end
34
34
  spec.bindir = 'exe'
35
35
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
@@ -68,23 +68,8 @@ files:
68
68
  - LICENSE.txt
69
69
  - README.md
70
70
  - Rakefile
71
- - assets/u-service_benchmarks.png
72
- - benchmarks/interactor/pipeline_failure.rb
73
- - benchmarks/interactor/pipeline_success.rb
74
- - benchmarks/interactor/service_failure.rb
75
- - benchmarks/interactor/service_success.rb
76
71
  - bin/console
77
72
  - bin/setup
78
- - comparisons/interactor.rb
79
- - comparisons/u-service.rb
80
- - examples/calculator/README.md
81
- - examples/calculator/Rakefile
82
- - examples/calculator/assets/usage.gif
83
- - examples/calculator/calc/normalize_args.rb
84
- - examples/calculator/calc/operation.rb
85
- - examples/calculator/calc/transform_into_numbers.rb
86
- - examples/rescuing_exceptions.rb
87
- - examples/users_creation.rb
88
73
  - lib/micro/service.rb
89
74
  - lib/micro/service/base.rb
90
75
  - lib/micro/service/pipeline.rb
Binary file
@@ -1,134 +0,0 @@
1
- require 'bundler/inline'
2
-
3
- gemfile do
4
- source 'https://rubygems.org'
5
-
6
- gem 'benchmark-ips', '~> 2.7', '>= 2.7.2'
7
- gem 'interactor', '~> 3.1', '>= 3.1.1'
8
- gem 'u-service', '~> 0.12.0'
9
- end
10
-
11
- require 'benchmark/ips'
12
-
13
- module IT
14
- class ConvertToNumbers
15
- include Interactor
16
-
17
- def call
18
- numbers = context.numbers
19
-
20
- if numbers.all? { |value| String(value) =~ /\d+/ }
21
- context.numbers = numbers.map(&:to_i)
22
- else
23
- context.fail! numbers: 'must contain only numeric types'
24
- end
25
- end
26
- end
27
-
28
- class Add2
29
- include Interactor
30
-
31
- def call
32
- numbers = context.numbers
33
-
34
- context.numbers = numbers.map { |number| number + 2 }
35
- end
36
- end
37
-
38
- class Add2ToAllNumbers
39
- include Interactor::Organizer
40
-
41
- organize ConvertToNumbers, Add2
42
- end
43
- end
44
-
45
- module MSB
46
- class ConvertToNumbers < Micro::Service::Base
47
- attribute :numbers
48
-
49
- def call!
50
- if numbers.all? { |value| String(value) =~ /\d+/ }
51
- Success(numbers: numbers.map(&:to_i))
52
- else
53
- Failure(numbers: 'must contain only numeric types')
54
- end
55
- end
56
- end
57
-
58
- class Add2 < Micro::Service::Base
59
- attribute :numbers
60
-
61
- def call!
62
- Success(numbers: numbers.map { |number| number + 2 })
63
- end
64
- end
65
-
66
- Add2ToAllNumbers = ConvertToNumbers >> Add2
67
- end
68
-
69
- module MSS
70
- class ConvertToNumbers < Micro::Service::Strict
71
- attribute :numbers
72
-
73
- def call!
74
- if numbers.all? { |value| String(value) =~ /\d+/ }
75
- Success(numbers: numbers.map(&:to_i))
76
- else
77
- Failure(numbers: 'must contain only numeric types')
78
- end
79
- end
80
- end
81
-
82
- class Add2 < Micro::Service::Strict
83
- attribute :numbers
84
-
85
- def call!
86
- Success(numbers: numbers.map { |number| number + 2 })
87
- end
88
- end
89
-
90
- Add2ToAllNumbers = ConvertToNumbers >> Add2
91
- end
92
-
93
- NUMBERS = {numbers: %w[1 1 2 2 c 4]}
94
-
95
- Benchmark.ips do |x|
96
- x.config(:time => 5, :warmup => 2)
97
-
98
- x.time = 5
99
- x.warmup = 2
100
-
101
- x.report('Interactor::Organizer') do
102
- IT::Add2ToAllNumbers.call(NUMBERS)
103
- end
104
-
105
- x.report('Pipeline of Micro::Service::Base') do
106
- MSB::Add2ToAllNumbers.call(NUMBERS)
107
- end
108
-
109
- x.report('Pipeline of Micro::Service::Strict') do
110
- MSS::Add2ToAllNumbers.call(NUMBERS)
111
- end
112
-
113
- x.compare!
114
- end
115
-
116
- # Warming up --------------------------------------
117
- # Interactor::Organizer
118
- # 2.355k i/100ms
119
- # Pipeline of Micro::Service::Base
120
- # 15.483k i/100ms
121
- # Pipeline of Micro::Service::Strict
122
- # 13.467k i/100ms
123
- # Calculating -------------------------------------
124
- # Interactor::Organizer
125
- # 23.767k (± 2.1%) i/s - 120.105k in 5.055726s
126
- # Pipeline of Micro::Service::Base
127
- # 166.013k (± 1.8%) i/s - 836.082k in 5.037938s
128
- # Pipeline of Micro::Service::Strict
129
- # 141.545k (± 2.1%) i/s - 713.751k in 5.044932s
130
-
131
- # Comparison:
132
- # Pipeline of Micro::Service::Base: 166013.1 i/s
133
- # Pipeline of Micro::Service::Strict: 141545.4 i/s - 1.17x slower
134
- # Interactor::Organizer: 23766.6 i/s - 6.99x slower
@@ -1,134 +0,0 @@
1
- require 'bundler/inline'
2
-
3
- gemfile do
4
- source 'https://rubygems.org'
5
-
6
- gem 'benchmark-ips', '~> 2.7', '>= 2.7.2'
7
- gem 'interactor', '~> 3.1', '>= 3.1.1'
8
- gem 'u-service', '~> 0.12.0'
9
- end
10
-
11
- require 'benchmark/ips'
12
-
13
- module IT
14
- class ConvertToNumbers
15
- include Interactor
16
-
17
- def call
18
- numbers = context.numbers
19
-
20
- if numbers.all? { |value| String(value) =~ /\d+/ }
21
- context.numbers = numbers.map(&:to_i)
22
- else
23
- context.fail! numbers: 'must contain only numeric types'
24
- end
25
- end
26
- end
27
-
28
- class Add2
29
- include Interactor
30
-
31
- def call
32
- numbers = context.numbers
33
-
34
- context.numbers = numbers.map { |number| number + 2 }
35
- end
36
- end
37
-
38
- class Add2ToAllNumbers
39
- include Interactor::Organizer
40
-
41
- organize ConvertToNumbers, Add2
42
- end
43
- end
44
-
45
- module MSB
46
- class ConvertToNumbers < Micro::Service::Base
47
- attribute :numbers
48
-
49
- def call!
50
- if numbers.all? { |value| String(value) =~ /\d+/ }
51
- Success(numbers: numbers.map(&:to_i))
52
- else
53
- Failure(numbers: 'must contain only numeric types')
54
- end
55
- end
56
- end
57
-
58
- class Add2 < Micro::Service::Base
59
- attribute :numbers
60
-
61
- def call!
62
- Success(numbers: numbers.map { |number| number + 2 })
63
- end
64
- end
65
-
66
- Add2ToAllNumbers = ConvertToNumbers >> Add2
67
- end
68
-
69
- module MSS
70
- class ConvertToNumbers < Micro::Service::Strict
71
- attribute :numbers
72
-
73
- def call!
74
- if numbers.all? { |value| String(value) =~ /\d+/ }
75
- Success(numbers: numbers.map(&:to_i))
76
- else
77
- Failure(numbers: 'must contain only numeric types')
78
- end
79
- end
80
- end
81
-
82
- class Add2 < Micro::Service::Strict
83
- attribute :numbers
84
-
85
- def call!
86
- Success(numbers: numbers.map { |number| number + 2 })
87
- end
88
- end
89
-
90
- Add2ToAllNumbers = ConvertToNumbers >> Add2
91
- end
92
-
93
- NUMBERS = {numbers: %w[1 1 2 2 3 4]}
94
-
95
- Benchmark.ips do |x|
96
- x.config(:time => 5, :warmup => 2)
97
-
98
- x.time = 5
99
- x.warmup = 2
100
-
101
- x.report('Interactor::Organizer') do
102
- IT::Add2ToAllNumbers.call(NUMBERS)
103
- end
104
-
105
- x.report('Pipeline of Micro::Service::Base') do
106
- MSB::Add2ToAllNumbers.call(NUMBERS)
107
- end
108
-
109
- x.report('Pipeline of Micro::Service::Strict') do
110
- MSS::Add2ToAllNumbers.call(NUMBERS)
111
- end
112
-
113
- x.compare!
114
- end
115
-
116
- # Warming up --------------------------------------
117
- # Interactor::Organizer
118
- # 5.047k i/100ms
119
- # Pipeline of Micro::Service::Base
120
- # 8.069k i/100ms
121
- # Pipeline of Micro::Service::Strict
122
- # 6.706k i/100ms
123
- # Calculating -------------------------------------
124
- # Interactor::Organizer
125
- # 50.656k (± 2.4%) i/s - 257.397k in 5.084184s
126
- # Pipeline of Micro::Service::Base
127
- # 83.309k (± 1.5%) i/s - 419.588k in 5.037749s
128
- # Pipeline of Micro::Service::Strict
129
- # 69.195k (± 1.7%) i/s - 348.712k in 5.041089s
130
-
131
- # Comparison:
132
- # Pipeline of Micro::Service::Base: 83309.3 i/s
133
- # Pipeline of Micro::Service::Strict: 69195.1 i/s - 1.20x slower
134
- # Interactor::Organizer: 50656.5 i/s - 1.64x slower
@@ -1,93 +0,0 @@
1
- require 'bundler/inline'
2
-
3
- gemfile do
4
- source 'https://rubygems.org'
5
-
6
- gem 'benchmark-ips', '~> 2.7', '>= 2.7.2'
7
- gem 'interactor', '~> 3.1', '>= 3.1.1'
8
- gem 'u-service', '~> 0.12.0'
9
- end
10
-
11
- require 'benchmark/ips'
12
-
13
- class IT_Multiply
14
- include Interactor
15
-
16
- def call
17
- a = context.a
18
- b = context.b
19
-
20
- if a.is_a?(Numeric) && b.is_a?(Numeric)
21
- context.number = a * b
22
- else
23
- context.fail!(type: :invalid_data)
24
- end
25
- end
26
- end
27
-
28
- class MSB_Multiply < Micro::Service::Base
29
- attributes :a, :b
30
-
31
- def call!
32
- if a.is_a?(Numeric) && b.is_a?(Numeric)
33
- Success(a * b)
34
- else
35
- Failure(:invalid_data)
36
- end
37
- end
38
- end
39
-
40
- class MSS_Multiply < Micro::Service::Strict
41
- attributes :a, :b
42
-
43
- def call!
44
- if a.is_a?(Numeric) && b.is_a?(Numeric)
45
- Success(a * b)
46
- else
47
- Failure(:invalid_data)
48
- end
49
- end
50
- end
51
-
52
- SYMBOL_KEYS = { a: nil, b: 2 }
53
- STRING_KEYS = { 'a' => 1, 'b' => '' }
54
-
55
- Benchmark.ips do |x|
56
- x.config(:time => 5, :warmup => 2)
57
-
58
- x.time = 5
59
- x.warmup = 2
60
-
61
- x.report('Interactor') do
62
- IT_Multiply.call(SYMBOL_KEYS)
63
- IT_Multiply.call(STRING_KEYS)
64
- end
65
-
66
- x.report('Micro::Service::Base') do
67
- MSB_Multiply.call(SYMBOL_KEYS)
68
- MSB_Multiply.call(STRING_KEYS)
69
- end
70
-
71
- x.report('Micro::Service::Strict') do
72
- MSS_Multiply.call(SYMBOL_KEYS)
73
- MSS_Multiply.call(STRING_KEYS)
74
- end
75
-
76
- x.compare!
77
- end
78
-
79
- # Warming up --------------------------------------
80
- # Interactor 1.507k i/100ms
81
- # Micro::Service::Base 12.902k i/100ms
82
- # Micro::Service::Strict
83
- # 9.758k i/100ms
84
- # Calculating -------------------------------------
85
- # Interactor 15.482k (± 2.6%) i/s - 78.364k in 5.065166s
86
- # Micro::Service::Base 134.861k (± 1.3%) i/s - 683.806k in 5.071263s
87
- # Micro::Service::Strict
88
- # 101.331k (± 1.5%) i/s - 507.416k in 5.008688s
89
-
90
- # Comparison:
91
- # Micro::Service::Base: 134861.1 i/s
92
- # Micro::Service::Strict: 101331.5 i/s - 1.33x slower
93
- # Interactor: 15482.0 i/s - 8.71x slower
@@ -1,93 +0,0 @@
1
- require 'bundler/inline'
2
-
3
- gemfile do
4
- source 'https://rubygems.org'
5
-
6
- gem 'benchmark-ips', '~> 2.7', '>= 2.7.2'
7
- gem 'interactor', '~> 3.1', '>= 3.1.1'
8
- gem 'u-service', '~> 0.12.0'
9
- end
10
-
11
- require 'benchmark/ips'
12
-
13
- class IT_Multiply
14
- include Interactor
15
-
16
- def call
17
- a = context.a
18
- b = context.b
19
-
20
- if a.is_a?(Numeric) && b.is_a?(Numeric)
21
- context.number = a * b
22
- else
23
- context.fail!(:invalid_data)
24
- end
25
- end
26
- end
27
-
28
- class MSB_Multiply < Micro::Service::Base
29
- attributes :a, :b
30
-
31
- def call!
32
- if a.is_a?(Numeric) && b.is_a?(Numeric)
33
- Success(a * b)
34
- else
35
- Failure(:invalid_data)
36
- end
37
- end
38
- end
39
-
40
- class MSS_Multiply < Micro::Service::Strict
41
- attributes :a, :b
42
-
43
- def call!
44
- if a.is_a?(Numeric) && b.is_a?(Numeric)
45
- Success(a * b)
46
- else
47
- Failure(:invalid_data)
48
- end
49
- end
50
- end
51
-
52
- SYMBOL_KEYS = { a: 2, b: 2 }
53
- STRING_KEYS = { 'a' => 1, 'b' => 1 }
54
-
55
- Benchmark.ips do |x|
56
- x.config(:time => 5, :warmup => 2)
57
-
58
- x.time = 5
59
- x.warmup = 2
60
-
61
- x.report('Interactor') do
62
- IT_Multiply.call(SYMBOL_KEYS)
63
- IT_Multiply.call(STRING_KEYS)
64
- end
65
-
66
- x.report('Micro::Service::Base') do
67
- MSB_Multiply.call(SYMBOL_KEYS)
68
- MSB_Multiply.call(STRING_KEYS)
69
- end
70
-
71
- x.report('Micro::Service::Strict') do
72
- MSS_Multiply.call(SYMBOL_KEYS)
73
- MSS_Multiply.call(STRING_KEYS)
74
- end
75
-
76
- x.compare!
77
- end
78
-
79
- # Warming up --------------------------------------
80
- # Interactor 2.943k i/100ms
81
- # Micro::Service::Base 12.540k i/100ms
82
- # Micro::Service::Strict
83
- # 9.584k i/100ms
84
- # Calculating -------------------------------------
85
- # Interactor 29.874k (± 2.7%) i/s - 150.093k in 5.027909s
86
- # Micro::Service::Base 131.440k (± 1.9%) i/s - 664.620k in 5.058327s
87
- # Micro::Service::Strict
88
- # 99.111k (± 2.2%) i/s - 498.368k in 5.031006s
89
-
90
- # Comparison:
91
- # Micro::Service::Base: 131440.3 i/s
92
- # Micro::Service::Strict: 99111.3 i/s - 1.33x slower
93
- # Interactor: 29873.6 i/s - 4.40x slower
@@ -1,57 +0,0 @@
1
- class CreateResponse
2
- include Interactor
3
-
4
- def call
5
- responder = context.responder
6
-
7
- survey_response = responder.survey_responses.build(
8
- response_text: context.answers[:text],
9
- rating: answers[:rating]
10
- survey: context.survey
11
- )
12
-
13
- if survey_response.save
14
- context.survey_response = survey_response
15
- else
16
- context.fail!(errors: survey_response.errors)
17
- end
18
- end
19
- end
20
-
21
- class AddRewardPoints
22
- include Interactor
23
-
24
- def call
25
- reward_account = context.responder.reward_account
26
-
27
- reward_account.balance += context.survey.reward_points
28
-
29
- unless reward_account.save
30
- context.fail!(errors: reward_account.errors)
31
- end
32
- end
33
- end
34
-
35
- class SendNotifications
36
- include Interactor
37
-
38
- def call
39
- sender = context.survey.sender
40
-
41
- SurveyMailer.delay.notify_responder(context.responder.id)
42
- SurveyMailer.delay.notify_sender(sender.id)
43
-
44
- unless sender.add_survey_response_notification
45
- context.fail!(errors: sender.errors)
46
- end
47
- end
48
- end
49
-
50
- class ReplyToSurvey
51
- include Interactor::Organizer
52
-
53
- organize CreateResponse, AddRewardPoints, SendNotifications
54
- end
55
-
56
- # https://gist.githubusercontent.com/raderj89/cbb84b1f75e67087388bc4cdbe617138/raw/a39c3ba6b416ac3919cc7d32bfa58e82211f24ef/interactor_example.rb
57
- # https://medium.com/reflektive-engineering/from-service-objects-to-interactors-db7d2bb7dfd9
@@ -1,61 +0,0 @@
1
- class CreateResponse < Micro::Service::Strict
2
- attributes :responder, :answers, :survey
3
-
4
- def call!
5
- survey_response = responder.survey_responses.build(
6
- response_text: answers[:text],
7
- rating: answers[:rating]
8
- survey: survey
9
- )
10
-
11
- return Success { attributes(:responder, :survey) } if survey_response.save
12
-
13
- Failure(:survey_response) { survey_response.errors }
14
- end
15
- end
16
-
17
- class AddRewardPoints < Micro::Service::Strict
18
- attributes :responder, :survey
19
-
20
- def call!
21
- reward_account = responder.reward_account
22
- reward_account.balance += survey.reward_points
23
-
24
- return Success { attributes(:responder, :survey) } if reward_account.save
25
-
26
- Failure(:reward_account) { reward_account.errors }
27
- end
28
- end
29
-
30
- class SendNotifications < Micro::Service::Strict
31
- attributes :responder, :survey
32
-
33
- def call!
34
- sender = survey.sender
35
-
36
- SurveyMailer.delay.notify_responder(responder.id)
37
- SurveyMailer.delay.notify_sender(sender.id)
38
-
39
- return Success { attributes(:survey) } if sender.add_survey_response_notification
40
-
41
- Failure(:sender) { sender.errors }
42
- end
43
- end
44
-
45
- ReplyToSurvey = CreateResponse >> AddRewardPoints >> SendNotifications
46
-
47
- # or
48
-
49
- ReplyToSurvey = Micro::Service::Pipeline[
50
- CreateResponse,
51
- AddRewardPoints,
52
- SendNotifications
53
- ]
54
-
55
- # or
56
-
57
- class ReplyToSurvey
58
- include Micro::Service::Pipeline
59
-
60
- pipeline CreateResponse, AddRewardPoints, SendNotifications
61
- end
@@ -1,56 +0,0 @@
1
- # μ-service - Calculator example
2
-
3
- This example uses [rake](http://rubygems.org/gems/rake) to expose a CLI calculator.
4
-
5
- ## Installation instructions
6
- ```sh
7
- gem install rake
8
- gem install u-service -v 0.12.0
9
- ```
10
-
11
- ### Usage
12
-
13
- ![gif](https://github.com/serradura/u-service/blob/master/examples/calculator/assets/usage.gif?raw=true)
14
-
15
- #### Listing the available rake tasks
16
- ```sh
17
- rake -T
18
-
19
- # rake calc:add[a,b] # adds two numbers
20
- # rake calc:divide[a,b] # divides two numbers
21
- # rake calc:multiply[a,b] # multiplies two numbers
22
- # rake calc:subtract[a,b] # subtracts two numbers
23
- ```
24
-
25
- #### Calculating integer numbers
26
- ```sh
27
- rake calc:add[3,2]
28
- # 3 + 2 = 5
29
-
30
- rake calc:subtract[3,2]
31
- # 3 - 2 = 1
32
-
33
- rake calc:multiply[3,2]
34
- # 3 x 2 = 6
35
-
36
- rake calc:divide[3,2]
37
- # 3 / 2 = 1
38
- ```
39
-
40
- #### Calculating float numbers
41
- ```sh
42
- rake calc:divide[3.0,2.0]
43
- # 3.0 / 2.0 = 1.5
44
-
45
- rake calc:divide[-3.0,2.0]
46
- # -3.0 / 2.0 = -1.5
47
- ```
48
-
49
- #### Calculation errors
50
- ```sh
51
- rake calc:add[1,a]
52
- # ERROR: The arguments must contain only numeric values
53
-
54
- rake calc:add[-\ 1,2]
55
- # ERROR: Arguments can't have spaces: a: "- 1", b: "2"
56
- ```
@@ -1,60 +0,0 @@
1
- require 'u-service'
2
-
3
- require_relative 'calc/operation'
4
- require_relative 'calc/normalize_args'
5
- require_relative 'calc/transform_into_numbers'
6
-
7
- module Calc
8
- TransformArgsIntoNumbers = NormalizeArgs >> TransformIntoNumbers
9
-
10
- module With
11
- Add = TransformArgsIntoNumbers >> Operation::Add
12
- Divide = TransformArgsIntoNumbers >> Operation::Divide
13
- Subtract = TransformArgsIntoNumbers >> Operation::Subtract
14
- Multiply = TransformArgsIntoNumbers >> Operation::Multiply
15
- end
16
- end
17
-
18
- class PerformTask < Micro::Service::Base
19
- attributes :args, :operation
20
-
21
- def call!
22
- operation
23
- .call(args: args)
24
- .on_success { |value| print_operation(value) }
25
- .on_failure(:not_a_number) { |message| puts "ERROR: #{message}" }
26
- .on_failure(:arguments_with_space_chars) do |(a, b)|
27
- puts "ERROR: Arguments can't have spaces: a: #{a}, b: #{b}"
28
- end
29
- end
30
-
31
- private def print_operation(a:, operator:, b:, result:)
32
- puts "#{a} #{operator} #{b} = #{result}"
33
- end
34
- end
35
-
36
- namespace :calc do
37
- desc 'adds two numbers'
38
- task :add, [:a, :b] do |_task, args|
39
- PerformTask.call(args: args, operation: Calc::With::Add)
40
- end
41
-
42
- desc 'divides two numbers'
43
- task :divide, [:a, :b] do |_task, args|
44
- begin
45
- PerformTask.call(args: args, operation: Calc::With::Divide)
46
- rescue ZeroDivisionError => e
47
- puts "ERROR: #{e.message}"
48
- end
49
- end
50
-
51
- desc 'subtracts two numbers'
52
- task :subtract, [:a, :b] do |_task, args|
53
- PerformTask.call(args: args, operation: Calc::With::Subtract)
54
- end
55
-
56
- desc 'multiplies two numbers'
57
- task :multiply, [:a, :b] do |_task, args|
58
- PerformTask.call(args: args, operation: Calc::With::Multiply)
59
- end
60
- end
Binary file
@@ -1,17 +0,0 @@
1
- module Calc
2
- class NormalizeArgs < Micro::Service::Base
3
- attributes :args
4
-
5
- def call!
6
- a, b = normalize(args[:a]), normalize(args[:b])
7
-
8
- return Success(a: a, b: b) if a !~ /\s/ && b !~ /\s/
9
-
10
- Failure(:arguments_with_space_chars) { [a.inspect, b.inspect] }
11
- end
12
-
13
- private def normalize(value)
14
- String(value).strip
15
- end
16
- end
17
- end
@@ -1,39 +0,0 @@
1
- class Operation < Micro::Service::Base
2
- attributes :a, :b
3
-
4
- private def result_of(operation_result)
5
- attributes(:a, :operator, :b).merge(result: operation_result)
6
- end
7
-
8
- class Add < Operation
9
- attribute :operator, '+'
10
-
11
- def call!
12
- Success(result_of(a + b))
13
- end
14
- end
15
-
16
- class Subtract < Operation
17
- attribute :operator, '-'
18
-
19
- def call!
20
- Success(result_of(a - b))
21
- end
22
- end
23
-
24
- class Multiply < Operation
25
- attribute :operator, 'x'
26
-
27
- def call!
28
- Success(result_of(a * b))
29
- end
30
- end
31
-
32
- class Divide < Operation
33
- attribute :operator, '/'
34
-
35
- def call!
36
- Success(result_of(a / b))
37
- end
38
- end
39
- end
@@ -1,18 +0,0 @@
1
- class TransformIntoNumbers < Micro::Service::Base
2
- attributes :a, :b
3
-
4
- def call!
5
- number_a, number_b = number(a), number(b)
6
-
7
- if number_a && number_b
8
- Success(a: number(a), b: number(b))
9
- else
10
- Failure(:not_a_number) { 'The arguments must contain only numeric values' }
11
- end
12
- end
13
-
14
- private def number(value)
15
- return value.to_i if value =~ /\A[\-,=]?\d+\z/
16
- return value.to_f if value =~ /\A[\-,=]?\d+\.\d+\z/
17
- end
18
- end
@@ -1,53 +0,0 @@
1
- require 'bundler/inline'
2
-
3
- gemfile do
4
- source 'https://rubygems.org'
5
-
6
- gem 'u-service', '~> 0.12.0'
7
- end
8
-
9
- class Divide < Micro::Service::Base
10
- attributes :a, :b
11
-
12
- def call!
13
- return Failure('numbers must be greater than 0') if a < 0 || b < 0
14
-
15
- Success(a / b)
16
- rescue => e
17
- Failure(e.message)
18
- end
19
- end
20
-
21
- #---------------------------------#
22
- puts "\n-- Success scenario --\n\n"
23
- #---------------------------------#
24
-
25
- result = Divide.call(a: 4, b: 2)
26
-
27
- puts result.value if result.success?
28
-
29
- #----------------------------------#
30
- puts "\n-- Failure scenarios --\n\n"
31
- #----------------------------------#
32
-
33
- result = Divide.call(a: 4, b: 0)
34
-
35
- puts result.value if result.failure?
36
-
37
- puts ''
38
-
39
- result = Divide.call(a: -4, b: 2)
40
-
41
- puts result.value if result.failure?
42
-
43
- # :: example of the output: ::
44
-
45
- # -- Success scenario --
46
- #
47
- # 2
48
- #
49
- # -- Failure scenarios --
50
- #
51
- # divided by 0
52
- #
53
- # numbers must be greater than 0
@@ -1,133 +0,0 @@
1
- require 'bundler/inline'
2
-
3
- gemfile do
4
- source 'https://rubygems.org'
5
-
6
- # NOTE: I used an older version of the Activemodel only to show the compatibility with its older versions.
7
- gem 'activemodel', '~> 3.2', '>= 3.2.22.5'
8
- gem 'u-service', '~> 0.12.0'
9
- end
10
-
11
- require 'micro/service/with_validation'
12
-
13
- module Users
14
- class Entity
15
- include Micro::Attributes.with(:initialize)
16
-
17
- attributes :id, :name, :email
18
-
19
- def persisted?
20
- !id.nil?
21
- end
22
- end
23
-
24
- module Creation
25
- require 'uri'
26
- require 'securerandom'
27
-
28
- class ProcessParams < Micro::Service::Base
29
- attributes :name, :email
30
-
31
- def call!
32
- Success(name: normalized_name, email: String(email).downcase.strip)
33
- end
34
-
35
- private def normalized_name
36
- String(name).strip.gsub(/\s+/, ' ')
37
- end
38
- end
39
-
40
- class ValidateParams < Micro::Service::WithValidation
41
- attributes :name, :email
42
-
43
- validates :name, presence: true
44
- validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
45
-
46
- def call!
47
- Success(attributes(:name, :email))
48
- end
49
- end
50
-
51
- class Persist < Micro::Service::Base
52
- attributes :name, :email
53
-
54
- def call!
55
- Success(user: Entity.new(user_data))
56
- end
57
-
58
- private def user_data
59
- attributes.merge(id: SecureRandom.uuid)
60
- end
61
- end
62
-
63
- class SendToCRM < Micro::Service::Base
64
- attribute :user
65
-
66
- def call!
67
- return Success(user_id: user.id, crm_id: send_to_crm) if user.persisted?
68
-
69
- Failure(:crm_error) { 'User can\'t be sent to the CRM' }
70
- end
71
-
72
- private def send_to_crm
73
- # Do some integration stuff...
74
- SecureRandom.uuid
75
- end
76
- end
77
-
78
- Process = ProcessParams >> ValidateParams >> Persist >> SendToCRM
79
- end
80
- end
81
-
82
- require 'pp'
83
-
84
- params = {
85
- "name" => " Rodrigo \n Serradura ",
86
- "email" => " RoDRIGo.SERRAdura@gmail.com "
87
- }
88
-
89
- #--------------------------------------#
90
- puts "\n-- Parameters processing --\n\n"
91
- #--------------------------------------#
92
-
93
- print 'Before: '
94
- p params
95
-
96
- print ' After: '
97
- Users::Creation::ProcessParams.call(params).on_success { |value| p value }
98
-
99
- #---------------------------------#
100
- puts "\n-- Success scenario --\n\n"
101
- #---------------------------------#
102
-
103
- Users::Creation::Process
104
- .call(params)
105
- .on_success do |user_id:, crm_id:|
106
- puts " CRM ID: #{crm_id}"
107
- puts "USER ID: #{user_id}"
108
- end
109
-
110
- #---------------------------------#
111
- puts "\n-- Failure scenario --\n\n"
112
- #---------------------------------#
113
-
114
- Users::Creation::Process
115
- .call(name: '', email: '')
116
- .on_failure { |errors:| p errors.full_messages }
117
-
118
-
119
- # :: example of the output: ::
120
-
121
- # -- Parameters processing --
122
- #
123
- # Before: {"name"=>" Rodrigo \n Serradura ", "email"=>" RoDRIGo.SERRAdura@gmail.com "}
124
- # After: {:name=>"Rodrigo Serradura", :email=>"rodrigo.serradura@gmail.com"}
125
- #
126
- # -- Success scenario --
127
- #
128
- # CRM ID: f3f189f6-ba6a-40ab-998c-c86773c41c83
129
- # USER ID: c140ffc3-6a7c-4554-972a-c2a0d59f8cb1
130
- #
131
- # -- Failure scenarios --
132
- #
133
- # ["Name can't be blank", "Email is invalid"]