services_base 0.1.0 → 1.0.1

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
- 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