services_base 0.1.0 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1a6c9556231cf5b53f1e17362a3a3d35e4ca9792
4
- data.tar.gz: be28c11b0980042cc3df8fbd92ade87509825d7b
2
+ SHA256:
3
+ metadata.gz: e08cc56780595fc4e0b65496e1c7390c38a750a9ed0ca0b6909e0bf42446d5bc
4
+ data.tar.gz: 80d6012ad972450cd9a18ed08dc9d299a5db68a1b9c640d2d851fae311b4233e
5
5
  SHA512:
6
- metadata.gz: 58fa5fe8fda0a7d13a7ea0a3703324bc631d4d5f1249888b375298d8cf587eb1b9d0ceaef298901b2de44c11be382c59b293aa9326ecc539ef6c2f022f262e25
7
- data.tar.gz: e8ec7e84e59be28abd2672c4b74ffe688b555c52dd41e95e031e9f4c86ae0ac2418246d0c20146bb8aebd8c3a276dce807b60df528494f3932591b8363de16ca
6
+ metadata.gz: e5423dd27046562d40eedb65aa57895c36d5ed4a39fdd008361a07738af818cc93e94c8073ea23c6592322e0f5edf620d0292a2635d5fcd0082a634cd182dac2
7
+ data.tar.gz: 7f893261a0dcbff1518a0043e6c5b0085d0a9f8e24bcb91f3553ef9b20a2c136932486275aadab14b383ad93dabc3e2bfb76e41f3f81178749a28747cc537488
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ *.gem
11
+ .byebug_history
data/Guardfile CHANGED
@@ -11,32 +11,4 @@ guard :rspec, cmd: "bundle exec rspec" do
11
11
  # Ruby files
12
12
  ruby = dsl.ruby
13
13
  dsl.watch_spec_files_for(ruby.lib_files)
14
-
15
- # # Rails files
16
- # rails = dsl.rails(view_extensions: %w(erb haml slim))
17
- # dsl.watch_spec_files_for(rails.app_files)
18
- # dsl.watch_spec_files_for(rails.views)
19
-
20
- # watch(rails.controllers) do |m|
21
- # [
22
- # rspec.spec.call("routing/#{m[1]}_routing"),
23
- # rspec.spec.call("controllers/#{m[1]}_controller"),
24
- # rspec.spec.call("acceptance/#{m[1]}")
25
- # ]
26
- # end
27
-
28
- # # Rails config changes
29
- # watch(rails.spec_helper) { rspec.spec_dir }
30
- # watch(rails.routes) { "#{rspec.spec_dir}/routing" }
31
- # watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
32
-
33
- # # Capybara features specs
34
- # watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") }
35
- # watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") }
36
-
37
- # # Turnip features and steps
38
- # watch(%r{^spec/acceptance/(.+)\.feature$})
39
- # watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
40
- # Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
41
- # end
42
14
  end
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # ServicesBase
2
2
 
3
- ServicesBase is a very simple Base module for implementing Service Objects and Micro-Services in Ruby.
3
+ ServicesBase is a very simple skeleton for implementing Service Objects and Micro-Services in Ruby.
4
+
5
+ It implements a Base module for your service objects (`Services::Base`) and two Response classes (`Services::Responses::Success` and `Services::Responses::Error`).
4
6
 
5
7
  It was heavily inspired by Chris Holtz's excellent article [Organize your app with service objects](http://chrisholtz.com/blog/organize-your-app-with-service-objects/). You should read it.
6
8
 
@@ -21,15 +23,52 @@ Or install it yourself as:
21
23
  $ gem install services_base
22
24
 
23
25
  ## Usage
26
+ ```ruby
27
+ class Services::MyService
28
+ include Services::Base
29
+
30
+ def call(id)
31
+ # do something
32
+ result_object = { foo: 'bar' }
33
+
34
+ # and return success
35
+ return Services::Responses::Success.new(result_object)
36
+
37
+ # or if there's an error:
38
+ return Services::Responses::Error.new(result_object, error_message: 'Something went wrong', error_code: 123)
39
+ end
40
+ end
41
+
42
+ response = Services::MyService.call(123)
43
+ response.is_a?(Services::Responses::Success) # true when it's a success
44
+ response.is_a?(Services::Responses::Error) # true when it's an error
45
+ response.is_a?(Services::Responses::Base) # always true
46
+
47
+ response.success? # true/false
48
+ response.result # the resulting object
49
+ response.error_code # available when there's an error
50
+ response.error_message # available when there's an error
51
+ ```
52
+
53
+ ## Configuration
54
+
55
+ When running a service asynchronously (ie: in Sidekiq or Delayed Job), it may be desirable to raise an exception instead of returning a `Services::Responses::Error` in order to retry the job at a later time. It is easy to do so:
24
56
 
25
- class Services::MyService
26
- include ServicesBase
57
+ ```ruby
58
+ Services::Responses.configure do |config|
59
+ config.raise_exception_on_async_error = true
60
+ end
61
+ ```
62
+
63
+ When `raise_exception_on_async_error` is set to `true`, an exception will be thrown whenever a new
64
+ `Services::Responses::Error` is initialized during an asynchronous job.
27
65
 
28
- def call(id)
29
- # do something
30
- end
31
- end
66
+ Alternatively, you can raise an exception only for a specific `Error` object:
32
67
 
68
+ ```ruby
69
+ # will raise an exception ONLY if it's called from an async job.
70
+ Services::Responses::Error.new(my_exception, raise_exception_on_async_error: true)
71
+ ```
33
72
 
34
73
  ## License
35
74
 
@@ -0,0 +1,21 @@
1
+ # Significantly inspired by http://chrisholtz.com/blog/organize-your-app-with-service-objects/
2
+ module Services
3
+ module Base
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ base.include InstanceMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ def call(*args, &block)
11
+ self.new.call *args, &block
12
+ end
13
+ end
14
+
15
+ module InstanceMethods
16
+ def call(*args, &block)
17
+ raise NotImplementedError
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module Services
2
+ module Responses
3
+ class Base
4
+ attr_reader :result
5
+
6
+ def initialize(result = nil)
7
+ @result = result
8
+ end
9
+
10
+ def success?
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def error?
15
+ !success?
16
+ end
17
+
18
+ def self.async_environment?
19
+ (defined?(Sidekiq) && !!Sidekiq.server?) || (ENV["_"] || "").include?("delayed_job") || (ENV["_"] || "").include?("resque")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ module Services::Responses
2
+ class << self
3
+ attr_accessor :configuration
4
+ end
5
+
6
+ def self.configure
7
+ yield(configuration)
8
+ end
9
+
10
+ class Configuration
11
+ attr_accessor :raise_exception_on_async_error
12
+
13
+ def initialize
14
+ @raise_exception_on_async_error = false
15
+ end
16
+ end
17
+ end
18
+
19
+ Services::Responses.configuration ||= Services::Responses::Configuration.new
@@ -0,0 +1,37 @@
1
+ module Services
2
+ module Responses
3
+ class Error < Services::Responses::Base
4
+ attr_accessor :error_message, :error_code, :exception
5
+
6
+ def initialize(result, error_message: nil, error_code: nil, exception: nil, raise_exception_on_async_error: nil)
7
+ @result, @error_message, @error_code, @exception, @raise_exception_on_async_error =
8
+ result, error_message, error_code, exception, raise_exception_on_async_error
9
+
10
+ raise_if_async!
11
+ end
12
+
13
+ def success?
14
+ false
15
+ end
16
+
17
+ protected
18
+ def raise_if_async!
19
+ return unless should_raise?
20
+
21
+ if @result.is_a?(Exception)
22
+ raise @result
23
+ elsif @exception
24
+ raise @exception
25
+ else
26
+ err = ("#{@error_message} " + "[#{@error_code}]".gsub("[]", "")).strip
27
+ raise StandardError.new(err)
28
+ end
29
+ end
30
+
31
+ def should_raise?
32
+ (Services::Responses.configuration.raise_exception_on_async_error || @raise_exception_on_async_error) \
33
+ && Services::Responses::Base.async_environment?
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ module Services
2
+ module Responses
3
+ class Success < Services::Responses::Base
4
+ def success?
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Services
2
+ VERSION = "1.0.1"
3
+ end
@@ -1,22 +1,6 @@
1
- require "services_base/version"
2
-
3
- # Significantly inspired by http://chrisholtz.com/blog/organize-your-app-with-service-objects/
4
- module ServicesBase
5
- def self.included(base)
6
- base.extend ClassMethods
7
- base.include InstanceMethods
8
- end
9
-
10
- module ClassMethods
11
- def call(*args, &block)
12
- @instance ||= self.new
13
- @instance.call *args, &block
14
- end
15
- end
16
-
17
- module InstanceMethods
18
- def call(*args, &block)
19
- raise NotImplementedError
20
- end
21
- end
22
- end
1
+ require "services/version"
2
+ require "services/base"
3
+ require "services/responses/base"
4
+ require "services/responses/error"
5
+ require "services/responses/success"
6
+ require "services/responses/configuration"
@@ -1,16 +1,16 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'services_base/version'
4
+ require 'services/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "services_base"
8
- spec.version = ServicesBase::VERSION
8
+ spec.version = Services::VERSION
9
9
  spec.authors = ["Carl Mercier"]
10
10
  spec.email = ["carl@varagesale.com"]
11
11
 
12
- spec.summary = %q{Simple Base module for implementing consistent Service Objects and Micro-Services in Ruby}
13
- spec.description = %q{Simple Base module for implementing consistent Service Objects and Micro-Services in Ruby}
12
+ spec.summary = %q{Simple skeleton for implementing consistent Service Objects and Micro-Services in Ruby}
13
+ spec.description = %q{Simple skeleton for implementing consistent Service Objects and Micro-Services in Ruby}
14
14
  spec.homepage = "https://github.com/varagesale/services_base"
15
15
  spec.license = "MIT"
16
16
 
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.10"
23
- spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "bundler"
23
+ spec.add_development_dependency "rake", "~> 12.3.3"
24
24
  spec.add_development_dependency "rspec"
25
25
  spec.add_development_dependency "guard"
26
26
  spec.add_development_dependency "guard-rspec"
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: services_base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carl Mercier
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-01 00:00:00.000000000 Z
11
+ date: 2020-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.10'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 12.3.3
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: 12.3.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +80,7 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- description: Simple Base module for implementing consistent Service Objects and Micro-Services
83
+ description: Simple skeleton for implementing consistent Service Objects and Micro-Services
84
84
  in Ruby
85
85
  email:
86
86
  - carl@varagesale.com
@@ -98,14 +98,19 @@ files:
98
98
  - Rakefile
99
99
  - bin/console
100
100
  - bin/setup
101
+ - lib/services/base.rb
102
+ - lib/services/responses/base.rb
103
+ - lib/services/responses/configuration.rb
104
+ - lib/services/responses/error.rb
105
+ - lib/services/responses/success.rb
106
+ - lib/services/version.rb
101
107
  - lib/services_base.rb
102
- - lib/services_base/version.rb
103
108
  - services_base.gemspec
104
109
  homepage: https://github.com/varagesale/services_base
105
110
  licenses:
106
111
  - MIT
107
112
  metadata: {}
108
- post_install_message:
113
+ post_install_message:
109
114
  rdoc_options: []
110
115
  require_paths:
111
116
  - lib
@@ -120,10 +125,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
125
  - !ruby/object:Gem::Version
121
126
  version: '0'
122
127
  requirements: []
123
- rubyforge_project:
124
- rubygems_version: 2.5.1
125
- signing_key:
128
+ rubygems_version: 3.1.4
129
+ signing_key:
126
130
  specification_version: 4
127
- summary: Simple Base module for implementing consistent Service Objects and Micro-Services
131
+ summary: Simple skeleton for implementing consistent Service Objects and Micro-Services
128
132
  in Ruby
129
133
  test_files: []
@@ -1,3 +0,0 @@
1
- module ServicesBase
2
- VERSION = "0.1.0"
3
- end