simple_ruby_service 1.0.2 → 1.0.3

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.
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: []