simple_ruby_service 1.0.2 → 1.0.3

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: 665fbb0eacfb11a6e7d863e72a0e091ad96831c0ce72644fb5467b592c567524
4
- data.tar.gz: 98c5caa24124671cd21f56a0f625f8c340e198c3847d05454b9cb41c633ff64b
3
+ metadata.gz: e42ccf4f74e452f3da1dddc21eafd66c9c20a84386bfd2e0434b19d97393db46
4
+ data.tar.gz: 92f5a6025b72f92144896272378d308e223474103dab3abfee7304eb11432fa5
5
5
  SHA512:
6
- metadata.gz: f11211b2e212d4324a9c55a09f2a366c152f5e3d53c5069c35d7b77876844cbc6db397e5bb888ceba36d1165ad27cc3dd09c8751cbd3bb838123f68c5695c4b5
7
- data.tar.gz: c1b45fe0900d696f739540cd9cd8f90d9c31133d8df14ebb2a60ad4743b90360241334c102dc70f1d26d4a8ee9415eb564d9631c401a3f633d7502b9b6b2c6be
6
+ metadata.gz: 4a983c65b09b6219e4ce3636e53837affde6667c3f5ffa888bc66742c7c7533590ba702515bb8340e326d5d9558114c22aada7d0d925645b8a8d616b7bb377e9
7
+ data.tar.gz: 18da46473f59e5c8ff97a36dea127fafd48cb71686d9d3a2f29deee80dc1843304d29b8c5ec10d6d09dce3d5fa6df3142f90bd472860f77579dccb0f4d150008
data/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 1.0.3 (01-Jul-21)
4
4
 
5
- * Finished Travis CI and Codecov integration
5
+ * Polished README
6
6
 
7
7
  ## 1.0.2 (01-Jul-21)
8
8
 
data/README.md CHANGED
@@ -3,13 +3,13 @@
3
3
  [![Build Status](https://travis-ci.com/amazing-jay/simple_ruby_service.svg?branch=master)](https://travis-ci.com/amazing-jay/simple_ruby_service)
4
4
  [![Test Coverage](https://codecov.io/gh/amazing-jay/simple_ruby_service/graph/badge.svg)](https://codecov.io/gh/amazing-jay/simple_ruby_service)
5
5
 
6
- Simple Ruby Service is a lightweight framework for Ruby that makes it easy to create Services and Service Objects (SOs).
6
+ Simple Ruby Service is a lightweight framework for creating Services and Service Objects (SOs) in Ruby.
7
7
 
8
8
  The framework provides a simple DSL that:
9
9
 
10
10
  1. Incorporates ActiveModel validations and error handling
11
11
  2. Encourages a succinct, idiomatic coding style
12
- 3. Ducktypes Service Objects as Procs
12
+ 3. Allows Service Objects to ducktype as Procs
13
13
 
14
14
  ## Requirements
15
15
 
@@ -37,10 +37,12 @@ Source code can be downloaded on GitHub
37
37
  [github.com/amazing-jay/simple_ruby_service/tree/master](https://github.com/amazing-jay/simple_ruby_service/tree/master)
38
38
 
39
39
 
40
- ### The following examples illustrate how to refactor complex business logic with Simple Ruby Service
40
+ ## Quick Start
41
41
 
42
42
  See [Usage](https://github.com/amazing-jay/simple_ruby_service#usage) & [Creating Simple Ruby Services](https://github.com/amazing-jay/simple_ruby_service#creating-simple-ruby-services) for more information.
43
43
 
44
+ ### How to refactor complex business logic with Simple Ruby Service
45
+
44
46
  #### ::Before:: Vanilla Rails with a fat controller (a contrived example)
45
47
  ```ruby
46
48
  # in app/controllers/some_controller.rb
@@ -51,6 +53,7 @@ class SomeController < ApplicationController
51
53
  authorize! resource
52
54
  resource.do_something
53
55
  value = resource.do_something_related
56
+ raise unless resource.errors
54
57
  render value
55
58
  end
56
59
  end
@@ -61,12 +64,39 @@ end
61
64
  # in app/controllers/some_controller.rb
62
65
  class SomeController < ApplicationController
63
66
  def show
64
- # NOTE: Simple Ruby Service Objects ducktype as Procs and do not need to be instantiated
65
- render DoSomething.call(params).value
67
+ # NOTE: Just one, readable line of code
68
+ render DoSomething.call!(params)
69
+ end
70
+ end
71
+ ```
72
+
73
+ #### ::Alternate After:: Refactored using a Service
74
+ ```ruby
75
+ # in app/controllers/some_controller.rb
76
+ class SomeController < ApplicationController
77
+ def show
78
+ # NOTE: Simple Ruby Service methods can be chained together
79
+ render SomeService.new(params)
80
+ .do_something
81
+ .do_something_related
82
+ .value
66
83
  end
67
84
  end
85
+ ```
68
86
 
87
+ ### Taking a peek under the hood
69
88
 
89
+ Similar to `ActiveRecord::Base#save!`, `DoSomething.call!(params)`:
90
+ - creates an instance of `DoSomething`
91
+ - initializes `instance.attributes` with `params`
92
+ - raises `SimpleRubyService::Invalid` if `instance.invalid?`
93
+ - sends `instance.call`
94
+ - raises `SimpleRubyService::Failed` if `instance.failed?`
95
+ - returns `instance.value` directly to the caller
96
+
97
+
98
+ ### Anatomy of a Simple Ruby Service Object
99
+ ```ruby
70
100
  # in app/service_objects/do_something.rb
71
101
  class DoSomething
72
102
  include SimpleRubyService::ServiceObject
@@ -74,33 +104,26 @@ class DoSomething
74
104
  attribute :id
75
105
  attr_accessor :resource
76
106
 
77
- # NOTE: Validations are executed prior to the business logic encapsulated in `perform`
107
+ # Validations are executed prior to the business logic encapsulated in `perform`
78
108
  validate do
79
109
  @resource ||= SomeModel.find(id)
80
110
  authorize! resource
81
111
  end
82
112
 
83
- # NOTE: The return value of `perform` is automatically stored as the SO's `value`
113
+ # The result of `perform` is automatically stored as the SO's `value`
84
114
  def perform
85
- resource.do_something
86
- resource.do_something_related
115
+ resource.do_something
116
+ result = resource.do_something_related
117
+
118
+ # Adding any kind of error indicates failure
119
+ add_errors_from_object resource
120
+ result
87
121
  end
88
122
  end
89
123
  ```
90
124
 
91
- #### ::Alternate Form:: Refactored using a Service
125
+ ### Anatomy of a Simple Ruby Service
92
126
  ```ruby
93
- # in app/controllers/some_controller.rb
94
- class SomeController < ApplicationController
95
- def show
96
- # NOTE: Simple Ruby Service methods can be chained together
97
- render SomeService.new(params)
98
- .do_something
99
- .do_something_related
100
- .value
101
- end
102
- end
103
-
104
127
  # in app/services/do_something.rb
105
128
  class SomeService
106
129
  include SimpleRubyService::Service
@@ -108,25 +131,38 @@ class SomeService
108
131
  attribute :id
109
132
  attr_accessor :resource
110
133
 
111
- # NOTE: Validations are executed prior to the first service method called
134
+ # Similar to SOs, validations are executed prior to the first service method called
112
135
  validate do
113
136
  @resource ||= SomeModel.find(id)
114
137
  authorize! @resource
115
138
  end
116
139
 
140
+ # Unlike SOs, Services can define an arbitrary number of service methods with arbitrary names
117
141
  service_methods do
118
142
  def do_something
119
- resource.do_something_related
143
+ resource.do_something
120
144
  end
121
145
 
122
- # NOTE: Unlike SOs, `value` must be explicitely set for Service methods
146
+ # Unlike SOs, `value` must be explicitely set for Service methods
123
147
  def do_something_related
124
148
  self.value ||= resource.tap &:do_something_related
149
+ add_errors_from_object resource
125
150
  end
126
151
  end
127
152
  end
128
153
  ```
129
154
 
155
+ ## A special note about Simple Ruby Service Objects, Procs, and Ducktyping
156
+
157
+ Simple Ruby Service Objects respond to (`#call`) so they can stand in for Procs, i.e.:
158
+ ```ruby
159
+ # in app/models/some_model.rb
160
+ class SomeModel < ApplicationRecord
161
+ validates :some_attribute, if: SomeServiceObject
162
+ [...]
163
+ ```
164
+ _See [To bang!, or not to bang](https://github.com/amazing-jay/simple_ruby_service/tree/master#to-bang-or-not-to-bang) to learn about `.call!` vs. `.call`._
165
+
130
166
  ## Usage
131
167
 
132
168
  ### Service Objects
@@ -137,8 +173,6 @@ Service Object names should begin with a verb and should not include the words `
137
173
 
138
174
  Also, only one operation should be made public, it should always be named `call`, and it should not accept arguments (except for an optional block).
139
175
 
140
- _See [To bang!, or not to bang](https://github.com/amazing-jay/simple_ruby_service/tree/master#to-bang-or-not-to-bang) to learn about `.call!` vs. `.call`._
141
-
142
176
  #### Short form (_recommended_)
143
177
 
144
178
  ```ruby
@@ -197,9 +231,6 @@ Unlike Service Objects, Service class names should begin with a noun (and may in
197
231
 
198
232
  Also, any number of operations may be made public, any of these operations may be named `call`, and any of these operations may accept arguments.
199
233
 
200
- _See [To bang!, or not to bang](https://github.com/amazing-jay/simple_ruby_service/tree/master#to-bang-or-not-to-bang) to learn about `.service_method_name!` vs. `.service_method_name`._
201
-
202
-
203
234
  #### Short form
204
235
 
205
236
  _not available for Services_
@@ -254,7 +285,7 @@ end
254
285
  ## Creating Simple Ruby Services
255
286
 
256
287
  ### Service Objects
257
- To implement an Simple Ruby Service Object:
288
+ To implement a Simple Ruby Service Object:
258
289
 
259
290
  1. include `SimpleRubyService::ServiceObject`
260
291
  2. declare attributes with the `attribute` keyword (class level DSL)
@@ -282,7 +313,7 @@ end
282
313
  ```
283
314
 
284
315
  ### Services
285
- To implement an Simple Ruby Service:
316
+ To implement a Simple Ruby Service:
286
317
 
287
318
  1. include `SimpleRubyService::Service`
288
319
  2. declare attributes with the `attribute` keyword (class level DSL)
@@ -323,9 +354,9 @@ end
323
354
 
324
355
  ### Why should I use Services & SOs?
325
356
 
326
- [Click here](https://www.google.com/search?q=service+object+pattern+rails&rlz=1C5CHFA_enUS893US893&oq=service+object+pattern+rails) to learn more about the Services & SO design pattern.
357
+ [LMGTFY](https://www.google.com/search?q=service+object+pattern+rails&rlz=1C5CHFA_enUS893US893&oq=service+object+pattern+rails) to learn more about the Services & SO design pattern.
327
358
 
328
- **TLDR; fat models and fat controllers are bad! Services and Service Objects help you DRY things up.**
359
+ **TLDR** - Fat models and fat controllers are bad! Services and Service Objects help you DRY things up.
329
360
 
330
361
  ### How is a Service different from an SO?
331
362
 
@@ -416,6 +447,7 @@ The gem is available as open source under the terms of the [MIT License](https:/
416
447
 
417
448
  ## DEVELOPMENT ROADMAP
418
449
 
419
- 1. Create a helper to dynamically generate default SOs for ActiveRecord models (`create`, `update`, and `destroy`) _(when used in a project that includes [ActiveRecord](https://github.com/rails/rails/tree/main/activerecord))_.
420
- 2. Consider isolating validation errors from execution errors (so that invalid? is not always true when failed? is true)
450
+ 1. Create a class level DSL to stop before each Service method unless errors.empty?
451
+ 2. Create a helper to dynamically generate default SOs for ActiveRecord models (`create`, `update`, and `destroy`) _(when used in a project that includes [ActiveRecord](https://github.com/rails/rails/tree/main/activerecord))_.
452
+ 3. Consider isolating validation errors from execution errors (so that invalid? is not always true when failed? is true)
421
453
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleRubyService
4
- VERSION = '1.0.2'
4
+ VERSION = '1.0.3'
5
5
  end
@@ -10,8 +10,8 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ["Jay Crouch"]
11
11
  spec.email = ["i.jaycrouch@gmail.com"]
12
12
 
13
- spec.summary = 'Simple Ruby Service is a lightweight framework for Ruby that makes it easy to create Services and Service Objects (SOs).'
14
- spec.description = 'Simple Ruby Service is a lightweight framework for Ruby that makes it easy to create Services and Service Objects (SOs). The framework provides a simple DSL that: incorporates ActiveModel validations and error handling; encourages a succinct, idiomatic coding style; Ducktypes Service Objects as Procs.'
13
+ spec.summary = 'Simple Ruby Service is a lightweight framework for creating Services and Service Objects (SOs) in Ruby.'
14
+ spec.description = 'Simple Ruby Service is a lightweight framework for creating Services and Service Objects (SOs) in Ruby. The framework provides a simple DSL that:\n a) incorporates ActiveModel validations and error handling;\n b) encourages a succinct, idiomatic coding style;\n c) allows Service Objects to ducktype as Procs.'
15
15
  spec.homepage = 'https://github.com/amazing-jay/simple_ruby_service'
16
16
  spec.license = "MIT"
17
17
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_ruby_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jay Crouch
@@ -304,10 +304,10 @@ dependencies:
304
304
  - - "~>"
305
305
  - !ruby/object:Gem::Version
306
306
  version: '3.13'
307
- description: 'Simple Ruby Service is a lightweight framework for Ruby that makes it
308
- easy to create Services and Service Objects (SOs). The framework provides a simple
309
- DSL that: incorporates ActiveModel validations and error handling; encourages a
310
- succinct, idiomatic coding style; Ducktypes Service Objects as Procs.'
307
+ description: Simple Ruby Service is a lightweight framework for creating Services
308
+ and Service Objects (SOs) in Ruby. The framework provides a simple DSL that:\n a)
309
+ incorporates ActiveModel validations and error handling;\n b) encourages a succinct,
310
+ idiomatic coding style;\n c) allows Service Objects to ducktype as Procs.
311
311
  email:
312
312
  - i.jaycrouch@gmail.com
313
313
  executables: []
@@ -358,6 +358,6 @@ requirements: []
358
358
  rubygems_version: 3.0.9
359
359
  signing_key:
360
360
  specification_version: 4
361
- summary: Simple Ruby Service is a lightweight framework for Ruby that makes it easy
362
- to create Services and Service Objects (SOs).
361
+ summary: Simple Ruby Service is a lightweight framework for creating Services and
362
+ Service Objects (SOs) in Ruby.
363
363
  test_files: []