command_service_object 0.5.10 → 0.5.11

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: fa75461af29202c5201ee4bf51357b26eb76a9d89401499fe28eb2ce57a26460
4
- data.tar.gz: 25b955a98a36b653a64c28a7c2adc517ce39f8d2a8fe31216fea3e72c14654e9
3
+ metadata.gz: 71a2cbd62d96248cddea4dc3cfbdeb6f07d1d43b62582eb573ca3e689322af01
4
+ data.tar.gz: 333ecebd2230edf5c67967d4fcfd526a81e0f51d50111ca95f264c543ae12d14
5
5
  SHA512:
6
- metadata.gz: 3cdc7896788d8e66861ec9fed7f63c0b8a68ee15408d227af8174cea3914c6a351c7f99aeb31c340b595bca07df77c7ef0bef09bbbd5af7829634ed352e613b4
7
- data.tar.gz: 41f52ac46e60b75966e210ab33a5363d5879a3adfa4ad8cd88d856bf0454adf2103c0dada86c2d260d81ab4821f562790c9d19e0b841449f14f2304837ea9551
6
+ metadata.gz: af30bd8432c0a1a045c152992e038381f64dc5cbd8882aff7bcc483ad8e5e86d24768df660c8502d2afeb2fad756f75edaeb9e12f28c67c40b604ff289906b42
7
+ data.tar.gz: dcace53060dc60e462025ca5dcb3d6ca93e440fc5f1ada54e587103ce18a6a35aa4dc50705a109d605c72212b8ec96600d1629edfd9d3cc39536568e0c147732
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- command_service_object (0.5.10)
4
+ command_service_object (0.5.11)
5
5
  virtus (~> 1.0, >= 1.0.5)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -2,21 +2,27 @@
2
2
 
3
3
  Rails Generator for command service object.
4
4
 
5
- ### Theory:
5
+ ## Theory
6
+
6
7
  [Command Design Pattern](https://en.wikipedia.org/wiki/Command_pattern) consists of `Command Object` and `Service Object` (Executor), Command object is responsible for containing `Client` requests and run input validations on it to ensure that the request is valid and set default values, then `Service Object` applies the business logic on that command.
7
8
 
8
- ### Implementation:
9
- Service consists of several objects { `Command Object` ` Usecase Object` And `Error Object` (business logic error) }.
9
+ ### Implementation
10
+
11
+ Service consists of several objects { `Command Object` `Usecase Object` And `Error Object` (business logic error) }.
10
12
 
11
13
  - **Command Object:** the object that responsible for containing `Client` requests and run input validations it's implemented using [Virtus](https://github.com/solnic/virtus) gem and can use `activerecord` for validations and it's existed under `commands` dir.
12
14
  - **Usecase Object:** this object responsible for executing the business logic, Every `usecase` should execute one command type only so that command name should be the same as usecase object name, usecase object existed under 'usecases` dir.
13
- - **Error Object:** business logic errors existed user `errors` dir inside the service dir.
15
+ - **Micros:** small reusable logic under the same service.
16
+
17
+ #### Result Object
14
18
 
15
- #### Result Object:
16
- In case of successful or failure `ApplicationService` the responsible object for all services will return `service_result` object this object contain `value!` method containing successful call result, and `errors` method containing failure `errors` objects.
19
+ In case of successful or failure `ApplicationService` the responsible object for all services will return `service_result` object this object contain `value!` method containing successful call result, and `errors` method containing failure `errors` objects.
17
20
 
18
- > You can check if the result successful or not by using `ok?` method.
21
+ #### Business Logic Failures
19
22
 
23
+ To raise bussiness logic failures you can use `fail!` helper method with `message: String, extra_data: Hash` arguments.
24
+
25
+ > You can check if the result successful or not by using `ok?` method.
20
26
 
21
27
  ## Installation
22
28
 
@@ -25,49 +31,69 @@ Add this line to your application's Gemfile:
25
31
  ```ruby
26
32
  gem 'command_service_object'
27
33
  ```
34
+
28
35
  And then execute:
29
36
 
30
- $ bundle
37
+ `bundle`
31
38
 
32
39
  Or install it yourself as:
33
40
 
34
- $ gem install command_service_object
41
+ `gem install command_service_object`
35
42
 
36
43
  Next, you need to run the generator:
37
44
 
38
- ```bash
39
- $ rails generate service:install
40
- ```
45
+ `rails generate service:install`
41
46
 
42
47
  ## Usage
43
48
 
44
- $ rails g service [service_name] [usecases usecases]
45
- ### Generate Service ex:
49
+ $ rails g service [service_name] [usecases usecases]
50
+
51
+ ### Generate Service ex
46
52
 
47
- $ rails g service auth login
53
+ $ rails g service auth login
48
54
  output
49
55
 
50
56
  ```bash
51
57
  app/services/
52
58
  ├── application_service.rb
59
+ ├── external/
53
60
  ├── auth_service
54
61
  │   ├── commands
55
62
  │   │   └── login.rb
56
63
  │   └── usecases
57
64
  │   ├── login.rb
58
- │   ├── login.rb
59
65
  │   └── micros
60
- │   └── user_profile_image.rb
61
66
  ├── case_base.rb
62
67
  └── service_result.rb
63
68
  ```
64
69
 
65
- ### Generate micros ex:
70
+ ### Generate micros ex
66
71
 
67
- $ rails g service:micro auth user_profile_image
72
+ $ rails g service:micro auth generate_jwt_token_for
73
+
74
+ ```bash
75
+ app/services/
76
+ ├── auth_service
77
+ │   └── usecases
78
+ │   └── micros
79
+ │   └── generate_jwt_token_for.rb
80
+ ```
81
+
82
+ ```ruby
83
+ # app/services/auth_service/usecases/micros/generate_jwt_token_for.rb
84
+
85
+ module PaymentService::Usecases::Micros
86
+ class GenerateJwtTokenFor < CaseBase
87
+ def call
88
+ # <Payload>
89
+ end
90
+ end
91
+ end
92
+ ```
68
93
 
69
94
  then you can edit command params
70
95
  > you can read [Virtus gem docs](https://github.com/solnic/virtus) for more info.
96
+
71
97
  ```ruby
72
98
  # app/services/auth_service/commands/login.rb
73
99
  # frozen_string_literal: true
@@ -87,7 +113,9 @@ module AuthService::Commands
87
113
  end
88
114
  end
89
115
  ```
116
+
90
117
  and then add your business logic
118
+
91
119
  ```ruby
92
120
  # app/services/auth_service/usecases/login.rb
93
121
  # frozen_string_literal: true
@@ -95,14 +123,13 @@ and then add your business logic
95
123
  module AuthService::Usecases
96
124
  class Login < CaseBase
97
125
  include CommandServiceObject::Hooks
98
- micros :user_profile_image
126
+ micros :generate_jwt_token_for
99
127
  #
100
128
  # Your business logic goes here, keep [call] method clean by using private
101
129
  # methods for Business logic.
102
130
  #
103
131
  def call
104
- result = user_profile_image(image_url) # set user profile image ex.
105
- balance = user_balance # get user balance ex.
132
+ token = generate_jwt_token_for(user)
106
133
  end
107
134
 
108
135
  # This method will run if call method raise error
@@ -117,10 +144,33 @@ module AuthService::Usecases
117
144
  end
118
145
  end
119
146
  end
147
+ ```
120
148
 
149
+ ### External APIs or Services
150
+
151
+ You can wrap external apis or services under `external/` dir
152
+
153
+ #### ex
154
+
155
+ ```ruby
156
+ module External
157
+ class StripeService
158
+ class << self
159
+ def charge(customer:, amount:, currency:, description: nil)
160
+ Stripe::Charge.create(
161
+ customer: customer.id,
162
+ amount: (round_up(amount, currency) * 100).to_i,
163
+ description: description || customer.email,
164
+ currency: currency
165
+ )
166
+ end
167
+ end
168
+ end
169
+ end
121
170
  ```
122
171
 
123
172
  usage from controller
173
+
124
174
  ```ruby
125
175
  class AuthenticationController < ApplicationController
126
176
  default_service :auth_service
@@ -5,7 +5,7 @@ require 'command_service_object/helpers/model_helper'
5
5
  require 'command_service_object/helpers/controller_helper'
6
6
  require 'command_service_object/helpers/failure_helper'
7
7
  require 'command_service_object/hooks'
8
- require_dependency 'virtus'
8
+ require 'virtus'
9
9
 
10
10
  if defined?(Rails) && Rails::VERSION::STRING >= '3.0'
11
11
  require 'command_service_object/railtie'
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/all'
4
+
3
5
  module CommandServiceObject
4
6
  module ControllerHelper
5
7
  def self.included(base)
@@ -26,32 +26,22 @@ module CommandServiceObject
26
26
  _called_micros.reverse_each(&:rollback)
27
27
  end
28
28
 
29
- def setup_getters(getters)
30
- getters.each do |getter|
31
- method_name = getter.name.split('::').last.underscore
32
-
33
- define_singleton_method(method_name) do |_payload|
34
- getter.new.call(args)
35
- end
36
- end
37
- end
38
-
39
29
  def setup_micros(micros)
40
30
  micros.each do |micro|
41
31
  method_name = micro.name.split('::').last.underscore
42
32
 
43
33
  # unrollable micros
44
- define_singleton_method("#{method_name}!") do |payload|
45
- micro.new(payload).call
34
+ define_singleton_method("#{method_name}!") do |cmd|
35
+ micro.new(cmd).call
46
36
  end
47
37
 
48
38
  # rollable micros
49
- define_singleton_method(method_name) do |payload|
50
- obj = micro.new(payload)
51
- obj.call
39
+ define_singleton_method(method_name) do |cmd|
40
+ obj = micro.new(cmd)
41
+ result = obj.call
52
42
 
53
43
  _called_micros << obj
54
- obj
44
+ result
55
45
  end
56
46
  end
57
47
  end
@@ -1,3 +1,3 @@
1
1
  module CommandServiceObject
2
- VERSION = '0.5.10'.freeze
2
+ VERSION = '0.5.11'.freeze
3
3
  end
@@ -6,24 +6,26 @@ class ApplicationService
6
6
  raise Errors::InvalidCommand, cmd.class if cmd.invalid?
7
7
 
8
8
  usecase = usecase_for(cmd).new(cmd)
9
- usecase.call
9
+ result = ServiceResult.new { usecase.call }
10
+
11
+ rollback(usecase, result, cmd) if result.error.present?
12
+ result
10
13
  rescue StandardError => e
11
- if usecase
12
- usecase.rollback_micros
13
- usecase.rollback
14
- end
15
- handle_failure(e)
16
- raise e
14
+ log_errors(e, cmd)
15
+ ServiceResult.new { raise e }
16
+ end
17
+
18
+ def rollback(usecase, result, cmd)
19
+ usecase.rollback_micros
20
+ usecase.rollback
21
+ log_errors(result.error, cmd)
17
22
  end
18
23
 
19
- def handle_failure(failure)
20
- # don't log custom failures if you want :D
21
- return if failure.class.is_a?(CommandServiceObject::Failure)
22
- #
24
+ def log_errors(err, _cmd)
25
+ return if err.class.is_a?(CommandServiceObject::Failure)
23
26
  # Add your logging logic
24
27
  # ex:
25
- # Rollbar.error(failure)
26
- #
28
+ # Rollbar.error(err)
27
29
  end
28
30
 
29
31
  private
@@ -3,10 +3,11 @@
3
3
  class CaseBase
4
4
  include CommandServiceObject::FailureHelper
5
5
 
6
- attr_reader :payload
6
+ attr_reader :cmd
7
+ alias_attribute :payload, :cmd
7
8
 
8
- def initialize(payload)
9
- @payload = payload
9
+ def initialize(cmd)
10
+ @cmd = cmd
10
11
  end
11
12
 
12
13
  def rollback; end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: command_service_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.10
4
+ version: 0.5.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adham EL-Deeb
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2019-07-07 00:00:00.000000000 Z
12
+ date: 2019-08-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler