simple_ruby_service 1.0.1 → 1.0.5

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: 43714cc68b788ec9560c521bea6b1f990c53df4355c1ea1926181a085d9995f5
4
- data.tar.gz: 663f185df7329f6c11af20451accc328d00a62ca5fef47f484fc2075ceaf1b88
3
+ metadata.gz: fb4a3799e6b103c84e39eb31420d97e98205847c21da94846dca68f99375243d
4
+ data.tar.gz: 00bd40999f571f0dddc67ac5437320628b2953a332ca87e3769c0b3bc46f14a3
5
5
  SHA512:
6
- metadata.gz: 9090c2b6e0cd08731df1094e0e9e1c73327b47c9c74ab853647fe0c48b898630a6800655e62a450d3a6ca932e14aeb807163129865b4bb9c2dcebf60c4f603ad
7
- data.tar.gz: 49ba2e1b78455023bbeb560da3a89d2ee30375fab1beda505f525c03e789fa9a71949b698f0c8d534cc1120fd34dd25a583163a28d2cb526861943e7b0b760d5
6
+ metadata.gz: b0331afb163c7f276e22b8ca2d7f536ec1850a462afa0f347ed5bcdf5af8aed19574ade60704f9eed49085a10b94376deb8298913baccbd8f7b809627e599f1c
7
+ data.tar.gz: bc68c8a83661057d86a71b7d932f39c5ad46078a5cd1d5bfa1a543ea5995551a789691435045af7653676b86a7c010a032cdbb9482c4ebe95e2b5f838586eea2
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ # SEE: https://docs.travis-ci.com/user/languages/ruby/
2
+
3
+ language: ruby
4
+ rvm:
5
+ - 2.5.3
6
+ before_install:
7
+ - gem install bundler:1.17.3
8
+ install: bundle _1.17.3_ install --jobs=3 --retry=3
9
+ env:
10
+ - 'TEST_RAILS_VERSION="~> 5.2.3"'
11
+ - 'TEST_RAILS_VERSION="~> 6.0.3"'
12
+ - 'TEST_RAILS_VERSION="~> 6.1.3.2"'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.4 (02-Jul-21)
4
+
5
+ * Polished README (again)
6
+
7
+ ## 1.0.3 (01-Jul-21)
8
+
9
+ * Polished README
10
+
11
+ ## 1.0.2 (01-Jul-21)
12
+
13
+ * Integrated Travis CI and Codecov
14
+
3
15
  ## 1.0.1 (01-Jul-21)
4
16
 
5
17
  * Renamed SimpleRubyservice to SimpleRubyService
data/README.md CHANGED
@@ -1,12 +1,33 @@
1
1
  # Simple Ruby Service
2
2
 
3
- Simple Ruby Service is a lightweight framework for Ruby that makes it easy to create Services and Service Objects (SOs).
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
+ [![Test Coverage](https://codecov.io/gh/amazing-jay/simple_ruby_service/graph/badge.svg)](https://codecov.io/gh/amazing-jay/simple_ruby_service)
4
5
 
5
- The framework provides a simple DSL that:
6
+ Simple Ruby Service is a lightweight framework for creating Services and Service Objects (SOs) in Ruby.
6
7
 
7
- 1. Adds ActiveModel validations and error handling
8
- 2. Encourages a succinct, idiomatic coding style
9
- 3. Allows Service Objects to ducktype as Procs
8
+ The framework makes Services and SOs look and feel like ActiveModels, complete with:
9
+
10
+ 1. Validations and robust error handling
11
+ 2. Workflows and method chaining
12
+ 3. Consistent interfaces
13
+
14
+ Additionally, Simple Ruby Service Objects can stand in for Procs, wherever Procs are expected (via ducktyping).
15
+
16
+ #### What problem does Simple Ruby Service solve?
17
+
18
+ Currently, most ruby developers roll their own services from scratch. As a result, most services are hastely built (in isolation), and this leads to inconsistant interfaces that are difficult to read. Also, error handling tends to vary wildly within an application, and support code tends to be implemented over and over again.
19
+
20
+ Simple Ruby Service addresses these problems and encourages succinct, idiomatic coding styles.
21
+
22
+ #### Should I be using Services & SOs in Ruby / Rails?
23
+
24
+ [LMGTFY](https://www.google.com/search?q=service+object+pattern+rails&rlz=1C5CHFA_enUS893US893&oq=service+object+pattern+rails) to learn more about Services & SOs.
25
+
26
+ **TLDR** - Fat models and fat controllers are bad! Services and Service Objects help you DRY things up.
27
+
28
+ #### How is a Service different from an SO?
29
+
30
+ An SO is just a Service that encapsulates a single operation (i.e. **one, and only one, responsibility**).
10
31
 
11
32
  ## Requirements
12
33
 
@@ -34,12 +55,15 @@ Source code can be downloaded on GitHub
34
55
  [github.com/amazing-jay/simple_ruby_service/tree/master](https://github.com/amazing-jay/simple_ruby_service/tree/master)
35
56
 
36
57
 
37
- ### The following examples illustrate how Simple Ruby Service can help you refactor complex business logic
58
+ ## Quick Start
38
59
 
39
60
  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.
40
61
 
62
+ ### How to refactor complex business logic with Simple Ruby Service
63
+
41
64
  #### ::Before:: Vanilla Rails with a fat controller (a contrived example)
42
65
  ```ruby
66
+ # in app/controllers/some_controller.rb
43
67
  class SomeController < ApplicationController
44
68
  def show
45
69
  raise unless params[:id].present?
@@ -47,77 +71,124 @@ class SomeController < ApplicationController
47
71
  authorize! resource
48
72
  resource.do_something
49
73
  value = resource.do_something_related
74
+ raise unless resource.errors
50
75
  render value
51
76
  end
52
77
  end
53
78
  ```
54
79
 
55
- #### ::After:: Refactored using an SO
80
+ #### ::After:: Refactored using an Simple Ruby Service Object
81
+ ```ruby
82
+ # in app/controllers/some_controller.rb
83
+ class SomeController < ApplicationController
84
+ def show
85
+ # NOTE: That's right... just one, readable line of code
86
+ render DoSomething.call!(params)
87
+ end
88
+ end
89
+ ```
90
+
91
+ #### ::Alternate After:: Refactored using a Simple Ruby Service
56
92
  ```ruby
93
+ # in app/controllers/some_controller.rb
57
94
  class SomeController < ApplicationController
58
95
  def show
59
- # NOTE: Simple Ruby Service Objects ducktype as Procs and do not need to be instantiated
60
- render DoSomething.call(params).value
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
+
105
+ ### Taking a peek under the hood
106
+
107
+ `DoSomething.call!(params)` is deliberately designed to look and feel like `ActiveRecord::Base#save!`.
108
+
109
+ The following (simplified) implementation illustrates what happens under the hood:
110
+
111
+ ```ruby
112
+ module SimpleRubyService::Object
113
+ def self.call!(params)
114
+ instance = new(params)
115
+ raise Invalid unless instance.valid?
116
+ self.value = instance.call
117
+ raise Invalid unless instance.failed?
118
+ value
61
119
  end
62
120
  end
121
+ ```
63
122
 
123
+ ### Anatomy of a Simple Ruby Service Object
124
+ ```ruby
125
+ # in app/service_objects/do_something.rb
64
126
  class DoSomething
65
127
  include SimpleRubyService::ServiceObject
66
128
 
129
+ # `attribute` behaves similar to ActiveRecord::Base#attribute, but is not typed, or bound to persistant storage
67
130
  attribute :id
68
131
  attr_accessor :resource
69
132
 
70
- # NOTE: Validations are executed prior to the business logic encapsulated in `perform`
133
+ # Validations are executed prior to the business logic encapsulated in `perform`
71
134
  validate do
72
135
  @resource ||= SomeModel.find(id)
73
136
  authorize! resource
74
137
  end
75
138
 
76
- # NOTE: The return value of `perform` is automatically stored as the SO's `value`
139
+ # The result of `perform` is automatically stored as the SO's `value`
77
140
  def perform
78
- resource.do_something
79
- resource.do_something_related
141
+ resource.do_something
142
+ result = resource.do_something_related
143
+
144
+ # Adding any kind of error indicates failure
145
+ add_errors_from_object resource
146
+ result
80
147
  end
81
148
  end
82
149
  ```
83
150
 
84
- #### ::Alternate Form:: Refactored using a Service
151
+ ### Anatomy of a Simple Ruby Service
85
152
  ```ruby
86
- class SomeController < ApplicationController
87
- def show
88
- # NOTE: Simple Ruby Service methods can be chained together
89
- render SomeService.new(params)
90
- .do_something
91
- .do_something_related
92
- .value
93
- end
94
- end
95
-
153
+ # in app/services/do_something.rb
96
154
  class SomeService
97
155
  include SimpleRubyService::Service
98
156
 
99
157
  attribute :id
100
158
  attr_accessor :resource
101
159
 
102
- # NOTE: Validations are executed prior to the first service method called
160
+ # Similar to SOs, validations are executed prior to the first service method called
103
161
  validate do
104
162
  @resource ||= SomeModel.find(id)
105
163
  authorize! @resource
106
164
  end
107
165
 
166
+ # Unlike SOs, Services can define an arbitrary number of service methods with arbitrary names
108
167
  service_methods do
109
168
  def do_something
110
- resource.do_something_related
169
+ resource.do_something
111
170
  end
112
171
 
113
- # NOTE: Unlike SOs, `value` must be explicitely set for Service methods
172
+ # Unlike SOs, `value` must be explicitely set for Service methods
114
173
  def do_something_related
115
174
  self.value ||= resource.tap &:do_something_related
175
+ add_errors_from_object resource
116
176
  end
117
177
  end
118
178
  end
119
179
  ```
120
180
 
181
+ ## A special note about Simple Ruby Service Objects, Procs, and Ducktyping
182
+
183
+ Simple Ruby Service Objects respond to (`#call`) so they can stand in for Procs, i.e.:
184
+ ```ruby
185
+ # in app/models/some_model.rb
186
+ class SomeModel < ApplicationRecord
187
+ validates :some_attribute, if: SomeServiceObject
188
+ [...]
189
+ ```
190
+ _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`._
191
+
121
192
  ## Usage
122
193
 
123
194
  ### Service Objects
@@ -128,8 +199,6 @@ Service Object names should begin with a verb and should not include the words `
128
199
 
129
200
  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).
130
201
 
131
- _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`._
132
-
133
202
  #### Short form (_recommended_)
134
203
 
135
204
  ```ruby
@@ -188,9 +257,6 @@ Unlike Service Objects, Service class names should begin with a noun (and may in
188
257
 
189
258
  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.
190
259
 
191
- _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`._
192
-
193
-
194
260
  #### Short form
195
261
 
196
262
  _not available for Services_
@@ -245,7 +311,7 @@ end
245
311
  ## Creating Simple Ruby Services
246
312
 
247
313
  ### Service Objects
248
- To implement an Simple Ruby Service Object:
314
+ To implement a Simple Ruby Service Object:
249
315
 
250
316
  1. include `SimpleRubyService::ServiceObject`
251
317
  2. declare attributes with the `attribute` keyword (class level DSL)
@@ -273,7 +339,7 @@ end
273
339
  ```
274
340
 
275
341
  ### Services
276
- To implement an Simple Ruby Service:
342
+ To implement a Simple Ruby Service:
277
343
 
278
344
  1. include `SimpleRubyService::Service`
279
345
  2. declare attributes with the `attribute` keyword (class level DSL)
@@ -310,19 +376,46 @@ class SomeService
310
376
  end
311
377
  ```
312
378
 
313
- ## FAQ
379
+ ### Workflows
380
+ Simple Ruby Services are inherently a good fit for workflows because they support chaining, i.e.:
314
381
 
315
- ### Why should I use Services & SOs?
382
+ ```ruby
383
+ SomeService.new(params)
384
+ .do_something
385
+ .do_something_related
386
+ .value
387
+ ```
316
388
 
317
- [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.
389
+ But SOs can also implement various workflows with dependency injection:
318
390
 
319
- **TLDR; fat models and fat controllers are bad! Services and Service Objects help you DRY things up.**
391
+ ```ruby
392
+ class PerformSomeWorkflow < SimpleRubyService::ServiceObject
393
+ def perform
394
+ dependency = SimpleRubyService1.call!
395
+ result = SimpleRubyService2.call(dependency)
396
+ raise unless result.success?
397
+ SimpleRubyService3(dependency, result.value).call!
398
+ end
399
+ end
400
+ ```
320
401
 
321
- ### How is a Service different from an SO?
402
+ ## MISC
322
403
 
323
- An SO is just a Service that encapsulates a single operation (i.e. **one, and only one, responsibility**).
404
+ ### To bang!, or not to bang
405
+
406
+ Use the bang! version of an operation whenever you expect the operation to succeed more often than fail, and you don't need to chain operations together.
407
+
408
+ Similar in pattern to `ActiveRecord#save!`, the bang version of each operation:
409
+ * raises `SimpleRubyService::Invalid` if `valid?` is falsey
410
+ * raises `SimpleRubyService::Failure` if the block provided returns a falsey value
411
+ * returns `@value`
324
412
 
325
- ### When should I choose a Service over an SO, and vice-versa?
413
+ Whereas, similar in pattern to `ActiveRecord#save`, the regular version of each operation:
414
+ * doesn't raise any exceptions
415
+ * passes the return value of the block provided to `#success?`
416
+ * returns self << _note: this is unlike `ActiveRecord#save`_
417
+
418
+ ### Service or SO?
326
419
 
327
420
  Use a `Service` when encapsulating related operations that share dependencies & validations.
328
421
 
@@ -333,9 +426,6 @@ i.e.:
333
426
 
334
427
  _note: Things get fuzzy when operations share some, but not all, dependencies & validations. Use your best judgement when operation `A` and operation `B` are related but `A` acts on a `User` while `B` acts on both a `User` & a `Company`._
335
428
 
336
- ### Atomicity
337
- The framework does not include transaction support by default. You are responsible for wrapping with a transaction if atomicity is desired.
338
-
339
429
  ### Control Flow
340
430
  Rescue exceptions that represent internal control flow and propogate the rest.
341
431
 
@@ -343,7 +433,7 @@ For example, if an internal call to User.create! is expected to always succeed,
343
433
 
344
434
  Example::
345
435
  ```ruby
346
- class DoSomethingDangerous < SimpleRubyService::ObjectBase
436
+ class DoSomethingDangerous < SimpleRubyService::ServiceObject
347
437
  attribute :attr1, :attr2 # should include all params required to execute
348
438
  validates_presence_of :attr1 # validate params to call
349
439
 
@@ -359,38 +449,6 @@ class DoSomethingDangerous < SimpleRubyService::ObjectBase
359
449
  end
360
450
  ```
361
451
 
362
- ## Workflows
363
- SOs often need to call other SOs in order to implement various workflows:
364
- ```ruby
365
- class PerformSomeWorkflow < SimpleRubyService::ObjectBase
366
- def perform
367
- dependency = SimpleRubyService1.call!
368
- result = SimpleRubyService2.call(dependency)
369
- raise unless result.success?
370
- SimpleRubyService3(dependency, result.value).call!
371
- end
372
- end
373
- ```
374
-
375
- ## MISC
376
-
377
- ### Attributes
378
- The `attribute` and `attributes` keywords behaves similar to [ActiveRecord::Base.attribute](https://api.rubyonrails.org/v6.1.3.1/classes/ActiveRecord/Attributes/ClassMethods.html), but they are not typed or bound to persistant storage.
379
-
380
- ### To bang!, or not to bang
381
-
382
- Use the bang! version of an operation whenever you expect the operation to succeed more often than fail, and you don't need to chain operations together.
383
-
384
- Similar in pattern to `ActiveRecord#save!`, the bang version of each operation:
385
- * raises `SimpleRubyService::Invalid` if `valid?` is falsey
386
- * raises `SimpleRubyService::Failure` if the block provided returns a falsey value
387
- * returns `@value`
388
-
389
- Whereas, similar in pattern to `ActiveRecord#save`, the regular version of each operation:
390
- * doesn't raise any exceptions
391
- * passes the return value of the block provided to `#success?`
392
- * returns self << _note: this is unlike `ActiveRecord#save`_
393
-
394
452
  ## Development
395
453
 
396
454
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -407,6 +465,7 @@ The gem is available as open source under the terms of the [MIT License](https:/
407
465
 
408
466
  ## DEVELOPMENT ROADMAP
409
467
 
410
- 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))_.
411
- 2. Consider isolating validation errors from execution errors (so that invalid? is not always true when failed? is true)
468
+ 1. Create a class level DSL to stop before each Service method unless errors.empty?
469
+ 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))_.
470
+ 3. Consider isolating validation errors from execution errors (so that invalid? is not always true when failed? is true)
412
471
 
@@ -6,6 +6,7 @@ module SimpleRubyService
6
6
  extend ActiveSupport::Concern
7
7
  include ActiveModel::AttributeAssignment
8
8
  include ActiveModel::Validations
9
+ include ActiveModel::Validations::Callbacks
9
10
 
10
11
  included do
11
12
  attr_accessor :value
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleRubyService
4
- VERSION = '1.0.1'
4
+ VERSION = '1.0.5'
5
5
  end
@@ -10,8 +10,9 @@ 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: adds ActiveModel validations and error handling; encourages a succinct, idiomatic coding style; and allows Service Objects to ducktype 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. ' \
15
+ 'The framework makes Services and SOs look and feel like ActiveModels, complete with: 1. validations and robust error handling; 2. workflows and method chaining; and 3. consistent interfaces. Additionally, Simple Ruby Service Objects can stand in for Procs, wherever Procs are expected (via ducktyping).'
15
16
  spec.homepage = 'https://github.com/amazing-jay/simple_ruby_service'
16
17
  spec.license = "MIT"
17
18
 
@@ -39,7 +40,6 @@ Gem::Specification.new do |spec|
39
40
  spec.add_dependency 'activemodel'
40
41
  spec.add_dependency 'activesupport'
41
42
 
42
- # spec.add_development_dependency 'actionpack'
43
43
  spec.add_development_dependency "awesome_print", "~> 1.9.2"
44
44
  spec.add_development_dependency "bundler", "~> 1.17"
45
45
  spec.add_development_dependency "database_cleaner", "~> 2.0.1"
@@ -48,13 +48,21 @@ Gem::Specification.new do |spec|
48
48
  spec.add_development_dependency "faker", "~> 2.18"
49
49
  spec.add_development_dependency "listen", "~> 3.5.1"
50
50
  spec.add_development_dependency "pry-byebug", "~> 3.9"
51
- spec.add_development_dependency "rails", "~> 6.1.3.2"
51
+
52
+ # must come before those below
53
+ if ENV['TEST_RAILS_VERSION'].nil?
54
+ spec.add_development_dependency 'rails', '~> 6.1.3.2'
55
+ else
56
+ spec.add_development_dependency 'rails', ENV['TEST_RAILS_VERSION'].to_s
57
+ end
58
+
52
59
  spec.add_development_dependency "rake", "~> 10.0"
53
60
  spec.add_development_dependency "rspec", "~> 3.0"
54
61
  spec.add_development_dependency "rspec-rails", "~> 5.0.1"
55
62
  spec.add_development_dependency "rubocop", "~> 0.60"
56
63
  spec.add_development_dependency "rubocop-performance", "~> 1.5"
57
64
  spec.add_development_dependency "rubocop-rspec", "~> 1.37"
65
+ spec.add_development_dependency "codecov", "~> 0.5.2"
58
66
  spec.add_development_dependency "simplecov", "~> 0.16"
59
67
  spec.add_development_dependency "sqlite3", "~> 1.4.2"
60
68
  spec.add_development_dependency "webmock", "~> 3.13"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_ruby_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jay Crouch
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-02 00:00:00.000000000 Z
11
+ date: 2021-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -248,6 +248,20 @@ dependencies:
248
248
  - - "~>"
249
249
  - !ruby/object:Gem::Version
250
250
  version: '1.37'
251
+ - !ruby/object:Gem::Dependency
252
+ name: codecov
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - "~>"
256
+ - !ruby/object:Gem::Version
257
+ version: 0.5.2
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - "~>"
263
+ - !ruby/object:Gem::Version
264
+ version: 0.5.2
251
265
  - !ruby/object:Gem::Dependency
252
266
  name: simplecov
253
267
  requirement: !ruby/object:Gem::Requirement
@@ -290,10 +304,11 @@ dependencies:
290
304
  - - "~>"
291
305
  - !ruby/object:Gem::Version
292
306
  version: '3.13'
293
- description: 'Simple Ruby Service is a lightweight framework for Ruby that makes it
294
- easy to create Services and Service Objects (SOs). The framework provides a simple
295
- DSL that: adds ActiveModel validations and error handling; encourages a succinct,
296
- idiomatic coding style; and allows Service Objects to ducktype as Procs.'
307
+ description: 'Simple Ruby Service is a lightweight framework for creating Services
308
+ and Service Objects (SOs) in Ruby. The framework makes Services and SOs look and
309
+ feel like ActiveModels, complete with: 1. validations and robust error handling;
310
+ 2. workflows and method chaining; and 3. consistent interfaces. Additionally, Simple
311
+ Ruby Service Objects can stand in for Procs, wherever Procs are expected (via ducktyping).'
297
312
  email:
298
313
  - i.jaycrouch@gmail.com
299
314
  executables: []
@@ -304,6 +319,7 @@ files:
304
319
  - ".rspec"
305
320
  - ".rubocop.yml"
306
321
  - ".simplecov"
322
+ - ".travis.yml"
307
323
  - CHANGELOG.md
308
324
  - Gemfile
309
325
  - LICENSE.txt
@@ -343,6 +359,6 @@ requirements: []
343
359
  rubygems_version: 3.0.9
344
360
  signing_key:
345
361
  specification_version: 4
346
- summary: Simple Ruby Service is a lightweight framework for Ruby that makes it easy
347
- to create Services and Service Objects (SOs).
362
+ summary: Simple Ruby Service is a lightweight framework for creating Services and
363
+ Service Objects (SOs) in Ruby.
348
364
  test_files: []