command_service_object 0.6.4 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +74 -61
  3. data/README.md +41 -22
  4. data/command_service_object.gemspec +2 -1
  5. data/lib/command_service_object.rb +1 -0
  6. data/lib/command_service_object/helpers/check_helper.rb +9 -0
  7. data/lib/command_service_object/version.rb +1 -1
  8. data/lib/generators/.DS_Store +0 -0
  9. data/lib/generators/service/command/command_generator.rb +23 -3
  10. data/lib/generators/service/{test/templates/rspec/command.rb.erb → command/templates/command_spec.rb.erb} +0 -0
  11. data/lib/generators/service/entity/entity_generator.rb +39 -0
  12. data/lib/generators/service/entity/templates/entity.rb.erb +9 -0
  13. data/lib/generators/service/external/external_generator.rb +46 -0
  14. data/lib/generators/service/external/templates/external.rb.erb +16 -0
  15. data/lib/generators/service/external/templates/external_spec.rb.erb +12 -0
  16. data/lib/generators/service/external/templates/external_test.rb.erb +0 -0
  17. data/lib/generators/service/helper.rb +23 -0
  18. data/lib/generators/service/install/templates/initializer.rb +5 -0
  19. data/lib/generators/service/install/templates/services/application_service.rb +57 -16
  20. data/lib/generators/service/install/templates/services/case_base.rb +4 -0
  21. data/lib/generators/service/install/templates/services/listener_base.rb +7 -0
  22. data/lib/generators/service/install/templates/services/query_base.rb +55 -0
  23. data/lib/generators/service/listener/listener_generator.rb +39 -0
  24. data/lib/generators/service/listener/templates/listener.rb.erb +11 -0
  25. data/lib/generators/service/micro/micro_generator.rb +11 -2
  26. data/lib/generators/service/query/USAGE +8 -0
  27. data/lib/generators/service/query/query_generator.rb +39 -0
  28. data/lib/generators/service/query/templates/query.rb.erb +22 -0
  29. data/lib/generators/service/service_generator.rb +13 -4
  30. data/lib/generators/service/setup/setup_generator.rb +20 -6
  31. data/lib/generators/service/setup/templates/doc.md.erb +39 -0
  32. data/lib/generators/service/usecase/templates/usecase.rb.erb +17 -3
  33. data/lib/generators/service/{test/templates/rspec/usecase.rb.erb → usecase/templates/usecase_spec.rb.erb} +0 -0
  34. data/lib/generators/service/usecase/usecase_generator.rb +22 -3
  35. metadata +40 -15
  36. data/lib/generators/service/getter/getter_generator.rb +0 -30
  37. data/lib/generators/service/getter/templates/getter.rb.erb +0 -8
  38. data/lib/generators/service/policies.rb +0 -5
  39. data/lib/generators/service/test/USAGE +0 -8
  40. data/lib/generators/service/test/templates/minitest/usecase.rb.erb +0 -1
  41. data/lib/generators/service/test/test_generator.rb +0 -72
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28de0190d89c14e5850b1de269a0e36fc0686e95ebf2d1051e7d2ab06a469dbb
4
- data.tar.gz: 61a880a5ab49bd1247333158c93c8286f22e9985a1806137a73f7cc146a6f96e
3
+ metadata.gz: f6713525d2c5f070d0e1f852b675d9a3afd12470cf124c151a816894c7f5328e
4
+ data.tar.gz: f76c2b168cac3af6d0fbb12cf07371168efa6b9a1c45fb2efa181cbf435af21f
5
5
  SHA512:
6
- metadata.gz: 7c1c4763e2e342ab1344674910c6a32bafe78cdf0bd19dabc4df66facd67b736cb2c6bee6582527e06ef5a28ff96f6f0ba936d8c6236bcf4e46baf012e703eac
7
- data.tar.gz: bb0b8c631d55ffd5cc18485bf2c5a9ff319fa8f54c21724ab4a2c3c47c3dbb0e6ecedff38b6f9dd6682d7c7cac8e99c8f32fed04edf4ed63fef09a7527298356
6
+ metadata.gz: 17b03115466551f6c9bdca3f16a92d9d15c25072d8f9dd401442ff3d8fa3f4ed190365c5bd47ff6d6cd2ac5c88fd2fd9dc300e7991230fe9440297360d683831
7
+ data.tar.gz: 7a829d7e6b32e37f9a162a6946170bb8437657bbbe03dfbb1fce8a969330555756186fff62969e49167f760eb6cdd63d776a0c3c1e52906c9bade6fc55f2b6c5
@@ -1,135 +1,148 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- command_service_object (0.6.4)
4
+ command_service_object (1.1.0)
5
+ hutch (~> 1.0)
5
6
  virtus (~> 1.0, >= 1.0.5)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
10
- actioncable (5.2.3)
11
- actionpack (= 5.2.3)
11
+ actioncable (5.2.4.4)
12
+ actionpack (= 5.2.4.4)
12
13
  nio4r (~> 2.0)
13
14
  websocket-driver (>= 0.6.1)
14
- actionmailer (5.2.3)
15
- actionpack (= 5.2.3)
16
- actionview (= 5.2.3)
17
- activejob (= 5.2.3)
15
+ actionmailer (5.2.4.4)
16
+ actionpack (= 5.2.4.4)
17
+ actionview (= 5.2.4.4)
18
+ activejob (= 5.2.4.4)
18
19
  mail (~> 2.5, >= 2.5.4)
19
20
  rails-dom-testing (~> 2.0)
20
- actionpack (5.2.3)
21
- actionview (= 5.2.3)
22
- activesupport (= 5.2.3)
23
- rack (~> 2.0)
21
+ actionpack (5.2.4.4)
22
+ actionview (= 5.2.4.4)
23
+ activesupport (= 5.2.4.4)
24
+ rack (~> 2.0, >= 2.0.8)
24
25
  rack-test (>= 0.6.3)
25
26
  rails-dom-testing (~> 2.0)
26
27
  rails-html-sanitizer (~> 1.0, >= 1.0.2)
27
- actionview (5.2.3)
28
- activesupport (= 5.2.3)
28
+ actionview (5.2.4.4)
29
+ activesupport (= 5.2.4.4)
29
30
  builder (~> 3.1)
30
31
  erubi (~> 1.4)
31
32
  rails-dom-testing (~> 2.0)
32
33
  rails-html-sanitizer (~> 1.0, >= 1.0.3)
33
- activejob (5.2.3)
34
- activesupport (= 5.2.3)
34
+ activejob (5.2.4.4)
35
+ activesupport (= 5.2.4.4)
35
36
  globalid (>= 0.3.6)
36
- activemodel (5.2.3)
37
- activesupport (= 5.2.3)
38
- activerecord (5.2.3)
39
- activemodel (= 5.2.3)
40
- activesupport (= 5.2.3)
37
+ activemodel (5.2.4.4)
38
+ activesupport (= 5.2.4.4)
39
+ activerecord (5.2.4.4)
40
+ activemodel (= 5.2.4.4)
41
+ activesupport (= 5.2.4.4)
41
42
  arel (>= 9.0)
42
- activestorage (5.2.3)
43
- actionpack (= 5.2.3)
44
- activerecord (= 5.2.3)
43
+ activestorage (5.2.4.4)
44
+ actionpack (= 5.2.4.4)
45
+ activerecord (= 5.2.4.4)
45
46
  marcel (~> 0.3.1)
46
- activesupport (5.2.3)
47
+ activesupport (5.2.4.4)
47
48
  concurrent-ruby (~> 1.0, >= 1.0.2)
48
49
  i18n (>= 0.7, < 2)
49
50
  minitest (~> 5.1)
50
51
  tzinfo (~> 1.1)
52
+ amq-protocol (2.3.2)
51
53
  arel (9.0.0)
52
54
  axiom-types (0.1.1)
53
55
  descendants_tracker (~> 0.0.4)
54
56
  ice_nine (~> 0.11.0)
55
57
  thread_safe (~> 0.3, >= 0.3.1)
56
- builder (3.2.3)
58
+ builder (3.2.4)
59
+ bunny (2.15.0)
60
+ amq-protocol (~> 2.3, >= 2.3.1)
57
61
  byebug (9.0.6)
62
+ carrot-top (0.0.7)
63
+ json
58
64
  coercible (1.0.0)
59
65
  descendants_tracker (~> 0.0.1)
60
- concurrent-ruby (1.1.5)
61
- crass (1.0.4)
66
+ concurrent-ruby (1.1.7)
67
+ crass (1.0.6)
62
68
  descendants_tracker (0.0.4)
63
69
  thread_safe (~> 0.3, >= 0.3.1)
64
70
  equalizer (0.0.11)
65
- erubi (1.8.0)
71
+ erubi (1.9.0)
66
72
  globalid (0.4.2)
67
73
  activesupport (>= 4.2.0)
68
- i18n (1.6.0)
74
+ hutch (1.0.0)
75
+ activesupport (>= 4.2, < 7)
76
+ bunny (>= 2.15, < 2.16)
77
+ carrot-top (~> 0.0.7)
78
+ multi_json (~> 1.14)
79
+ i18n (1.8.5)
69
80
  concurrent-ruby (~> 1.0)
70
81
  ice_nine (0.11.2)
71
- loofah (2.2.3)
82
+ json (2.3.1)
83
+ loofah (2.7.0)
72
84
  crass (~> 1.0.2)
73
85
  nokogiri (>= 1.5.9)
74
86
  mail (2.7.1)
75
87
  mini_mime (>= 0.1.1)
76
88
  marcel (0.3.3)
77
89
  mimemagic (~> 0.3.2)
78
- method_source (0.9.2)
79
- mimemagic (0.3.3)
80
- mini_mime (1.0.1)
90
+ method_source (1.0.0)
91
+ mimemagic (0.3.5)
92
+ mini_mime (1.0.2)
81
93
  mini_portile2 (2.4.0)
82
- minitest (5.11.3)
83
- nio4r (2.3.1)
84
- nokogiri (1.10.4)
94
+ minitest (5.14.2)
95
+ multi_json (1.15.0)
96
+ nio4r (2.5.4)
97
+ nokogiri (1.10.10)
85
98
  mini_portile2 (~> 2.4.0)
86
- rack (2.0.7)
99
+ rack (2.2.3)
87
100
  rack-test (1.1.0)
88
101
  rack (>= 1.0, < 3)
89
- rails (5.2.3)
90
- actioncable (= 5.2.3)
91
- actionmailer (= 5.2.3)
92
- actionpack (= 5.2.3)
93
- actionview (= 5.2.3)
94
- activejob (= 5.2.3)
95
- activemodel (= 5.2.3)
96
- activerecord (= 5.2.3)
97
- activestorage (= 5.2.3)
98
- activesupport (= 5.2.3)
102
+ rails (5.2.4.4)
103
+ actioncable (= 5.2.4.4)
104
+ actionmailer (= 5.2.4.4)
105
+ actionpack (= 5.2.4.4)
106
+ actionview (= 5.2.4.4)
107
+ activejob (= 5.2.4.4)
108
+ activemodel (= 5.2.4.4)
109
+ activerecord (= 5.2.4.4)
110
+ activestorage (= 5.2.4.4)
111
+ activesupport (= 5.2.4.4)
99
112
  bundler (>= 1.3.0)
100
- railties (= 5.2.3)
113
+ railties (= 5.2.4.4)
101
114
  sprockets-rails (>= 2.0.0)
102
115
  rails-dom-testing (2.0.3)
103
116
  activesupport (>= 4.2.0)
104
117
  nokogiri (>= 1.6)
105
- rails-html-sanitizer (1.0.4)
106
- loofah (~> 2.2, >= 2.2.2)
107
- railties (5.2.3)
108
- actionpack (= 5.2.3)
109
- activesupport (= 5.2.3)
118
+ rails-html-sanitizer (1.3.0)
119
+ loofah (~> 2.3)
120
+ railties (5.2.4.4)
121
+ actionpack (= 5.2.4.4)
122
+ activesupport (= 5.2.4.4)
110
123
  method_source
111
124
  rake (>= 0.8.7)
112
125
  thor (>= 0.19.0, < 2.0)
113
- rake (10.5.0)
114
- sprockets (3.7.2)
126
+ rake (13.0.1)
127
+ sprockets (4.0.2)
115
128
  concurrent-ruby (~> 1.0)
116
129
  rack (> 1, < 3)
117
- sprockets-rails (3.2.1)
130
+ sprockets-rails (3.2.2)
118
131
  actionpack (>= 4.0)
119
132
  activesupport (>= 4.0)
120
133
  sprockets (>= 3.0.0)
121
134
  thor (0.20.3)
122
135
  thread_safe (0.3.6)
123
- tzinfo (1.2.5)
136
+ tzinfo (1.2.7)
124
137
  thread_safe (~> 0.1)
125
138
  virtus (1.0.5)
126
139
  axiom-types (~> 0.1)
127
140
  coercible (~> 1.0)
128
141
  descendants_tracker (~> 0.0, >= 0.0.3)
129
142
  equalizer (~> 0.0, >= 0.0.9)
130
- websocket-driver (0.7.0)
143
+ websocket-driver (0.7.3)
131
144
  websocket-extensions (>= 0.1.0)
132
- websocket-extensions (0.1.3)
145
+ websocket-extensions (0.1.5)
133
146
 
134
147
  PLATFORMS
135
148
  ruby
@@ -140,8 +153,8 @@ DEPENDENCIES
140
153
  command_service_object!
141
154
  minitest (~> 5.11, >= 5.11.3)
142
155
  rails (~> 5.0)
143
- rake (~> 10.0)
156
+ rake (~> 13.0)
144
157
  thor (~> 0.20.3)
145
158
 
146
159
  BUNDLED WITH
147
- 2.0.2
160
+ 2.1.4
data/README.md CHANGED
@@ -8,19 +8,24 @@ Rails Generator for command service object.
8
8
 
9
9
  ### Implementation
10
10
 
11
- Service consists of several objects { `Command Object` `Usecase Object` And `Error Object` (business logic error) }.
11
+ Service consists of several objects { `Command Object` `Usecase Object` And `Error Object` (business logic error) }.
12
12
 
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.
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.
15
- - **Micros:** small reusable logic under the same service.
13
+ - **[Command](https://en.wikipedia.org/wiki/Command_pattern):** 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.
14
+ - **Usecase:** 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.
15
+ - **Micros:** Small reusable logic under the same service.
16
+ - **Externals:** Simple ruby module works as a service interface whenever you wanna call any external service or even service that lives under the same project you should use it.
17
+ - **Queries:** This dir is the only entry point for you to get any data form a service.
18
+ - **Listeners:** An event listener that waits for an event outside the service to occur.
19
+ - **Entities:** Many objects are not fundamentally defined by their attributes, but rather by a thread of continuity and identity.
16
20
 
17
- #### Result Object
21
+ ### Result Object
18
22
 
19
23
  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.
20
24
 
21
- #### Business Logic Failures
25
+ ### Helpers:
22
26
 
23
- To raise bussiness logic failures you can use `fail!` helper method with `message: String, extra_data: Hash` arguments.
27
+ - Fail: You can use `fail!` helper to raise business logic failures, ex: `fail!('user should not have any active cards')`.
28
+ - Check: To do business logic validations you can use `check!` helper ex: `check!('user should not have any active cards') { user.active_cards.empty? }`, if the given block returns false then it will raise fail! with the given message.
24
29
 
25
30
  > You can check if the result successful or not by using `ok?` method.
26
31
 
@@ -56,8 +61,8 @@ output
56
61
  ```bash
57
62
  app/services/
58
63
  ├── application_service.rb
59
- ├── external/
60
64
  ├── auth_service
65
+ │ ├ external/
61
66
  │   ├── commands
62
67
  │   │   └── login.rb
63
68
  │   └── usecases
@@ -99,11 +104,9 @@ then you can edit command params
99
104
  # frozen_string_literal: true
100
105
 
101
106
  module AuthService::Commands
102
- class Login
107
+ class Login < CommandBase
103
108
  # You can read Virtus gem doc for more info.
104
109
  # https://github.com/solnic/virtus
105
- include Virtus.model
106
- include ActiveModel::Validations
107
110
 
108
111
  # Attributes
109
112
  # attribute :REPLACE_ME, String
@@ -129,13 +132,29 @@ module AuthService::Usecases
129
132
  # methods for Business logic.
130
133
  #
131
134
  def call
132
- token = generate_jwt_token_for(user)
135
+ token = generate_jwt_token_for(cmd.user)
136
+ replace_me
137
+
138
+ output
139
+ end
140
+
141
+ def output
142
+ # return entity object
133
143
  end
134
144
 
135
145
  # This method will run if call method raise error
136
146
  def rollback
137
147
  # rollback logic
138
148
  end
149
+
150
+ def allowed?
151
+ # policies loginc for issuer
152
+ # ex:
153
+ #
154
+ # return false if issuer.role != :admin
155
+
156
+ true
157
+ end
139
158
 
140
159
  private
141
160
 
@@ -154,16 +173,16 @@ You can wrap external apis or services under `external/` dir
154
173
 
155
174
  ```ruby
156
175
  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
176
+ module StripeService
177
+ extend self
178
+
179
+ def charge(customer:, amount:, currency:, description: nil)
180
+ Stripe::Charge.create(
181
+ customer: customer.id,
182
+ amount: (round_up(amount, currency) * 100).to_i,
183
+ description: description || customer.email,
184
+ currency: currency
185
+ )
167
186
  end
168
187
  end
169
188
  end
@@ -36,8 +36,9 @@ Gem::Specification.new do |spec|
36
36
  spec.add_development_dependency 'byebug', '~> 9.0.6'
37
37
  spec.add_development_dependency 'minitest', '~> 5.11', '>= 5.11.3'
38
38
  spec.add_development_dependency 'rails', '~> 5.0'
39
- spec.add_development_dependency 'rake', '~> 10.0'
39
+ spec.add_development_dependency 'rake', '~> 13.0'
40
40
  spec.add_development_dependency 'thor', '~> 0.20.3'
41
41
 
42
42
  spec.add_dependency 'virtus', '~> 1.0', '>= 1.0.5'
43
+ spec.add_dependency 'hutch', '~> 1.0'
43
44
  end
@@ -4,6 +4,7 @@ require 'command_service_object/failure'
4
4
  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
+ require 'command_service_object/helpers/check_helper'
7
8
  require 'command_service_object/hooks'
8
9
  require 'virtus'
9
10
 
@@ -0,0 +1,9 @@
1
+ module CommandServiceObject
2
+ module CheckHelper
3
+ def check!(message, &block)
4
+ raise "No block given" unless block_given?
5
+
6
+ fail!(message) unless block.call
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module CommandServiceObject
2
- VERSION = '0.6.4'.freeze
2
+ VERSION = '1.2.1'.freeze
3
3
  end
Binary file
@@ -1,4 +1,5 @@
1
1
  require_relative '../setup/setup_generator.rb'
2
+ require_relative '../helper'
2
3
 
3
4
  module Service
4
5
  module Generators
@@ -12,17 +13,36 @@ module Service
12
13
  def call
13
14
  invoke Service::Generators::SetupGenerator, [name]
14
15
  @model_attributes = model_attributes
16
+
15
17
  commands.each do |c|
16
18
  @command = c.classify
17
- path = "app/services/#{service_name}/commands/#{c.underscore}.rb"
18
- template 'command.rb.erb', path unless options.skip_command?
19
+ create_main(c)
20
+ create_test(c)
19
21
  end
20
22
  end
21
23
 
22
24
  private
23
25
 
26
+ def create_main(m)
27
+ path = "#{service_path}/commands/#{m.underscore}.rb"
28
+ template 'command.rb.erb', path unless options.skip_command?
29
+ end
30
+
31
+ def create_test(m)
32
+ path = "#{spec_path}/commands/#{m.underscore}_spec.rb"
33
+ template 'command_spec.rb.erb', path
34
+ end
35
+
24
36
  def service_name
25
- "#{name.underscore}_service"
37
+ Service::Helper.service_name(name)
38
+ end
39
+
40
+ def service_path
41
+ Service::Helper.service_path(name)
42
+ end
43
+
44
+ def spec_path
45
+ Service::Helper.spec_path(name)
26
46
  end
27
47
  end
28
48
  end
@@ -0,0 +1,39 @@
1
+ require_relative '../setup/setup_generator.rb'
2
+ require_relative '../helper'
3
+
4
+ module Service
5
+ module Generators
6
+ class EntityGenerator < Rails::Generators::NamedBase
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+ argument :entities, type: :array, default: [], banner: 'entities entities'
10
+
11
+ def setup
12
+ invoke Service::Generators::SetupGenerator, [name]
13
+ end
14
+
15
+ def create_micros
16
+ entities.each do |m|
17
+ @entity = m.classify
18
+
19
+ path = "#{service_path}/entities/#{m.underscore}.rb"
20
+ template 'entity.rb.erb', path
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def service_name
27
+ Service::Helper.service_name(name)
28
+ end
29
+
30
+ def service_path
31
+ Service::Helper.service_path(name)
32
+ end
33
+
34
+ def spec_path
35
+ Service::Helper.spec_path(name)
36
+ end
37
+ end
38
+ end
39
+ end