solidservice 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +10 -0
- data/README.md +150 -12
- data/lib/solidservice/base.rb +69 -0
- data/lib/solidservice/error.rb +10 -0
- data/lib/solidservice/failure.rb +4 -0
- data/lib/solidservice/state.rb +20 -0
- data/lib/solidservice/success.rb +4 -0
- data/lib/solidservice/version.rb +1 -1
- data/lib/solidservice.rb +8 -2
- data/matrixeval.yml +77 -0
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f392725c3e702c59ac368f8b437d4e16a4485f7326b35b818d38cc1225e8098
|
4
|
+
data.tar.gz: d26bab0fb422776548372ed8da261ac18ad0f0040a3d520d48f80bea6866b1fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 237fc7a04efec213147e501c52fbcd71b1d26463d75ffceb1e63f0317acd65f45876265726880a99bd3ce9862c1ac68602be12d4e0b51aa8ed44084e9b031dda
|
7
|
+
data.tar.gz: 836fe0f7b0026cee670295d3f911a3c6bdfc0ab1a26c1bc20cd0f421324233e67301021319265fcbcefb2aa5c0049f87e024ec4be4e32ba0a95c827d3fd529c7
|
data/Gemfile
CHANGED
@@ -2,9 +2,19 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
+
if rails_version = ENV['RAILS_VERSION']
|
6
|
+
gem 'rails', rails_version
|
7
|
+
end
|
8
|
+
|
5
9
|
# Specify your gem's dependencies in solidservice.gemspec
|
6
10
|
gemspec
|
7
11
|
|
8
12
|
gem "rake", "~> 13.0"
|
9
13
|
|
10
14
|
gem "minitest", "~> 5.0"
|
15
|
+
|
16
|
+
group :development, :test do
|
17
|
+
gem "debug"
|
18
|
+
gem 'matrixeval-ruby'
|
19
|
+
gem 'simplecov'
|
20
|
+
end
|
data/README.md
CHANGED
@@ -1,32 +1,170 @@
|
|
1
1
|
# SolidService
|
2
2
|
|
3
|
-
|
3
|
+
[![CI](https://github.com/hoppergee/solidservice/actions/workflows/main.yml/badge.svg)](https://github.com/hoppergee/solidservice/actions/workflows/main.yml)
|
4
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/625ef769e60ab39159ce/maintainability)](https://codeclimate.com/github/hoppergee/solidservice/maintainability)
|
5
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/625ef769e60ab39159ce/test_coverage)](https://codeclimate.com/github/hoppergee/solidservice/test_coverage)
|
4
6
|
|
5
|
-
|
7
|
+
Servcie object with a simple API.
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
result = ASolidService.call(any: 'thing', you: 'like')
|
11
|
+
result.success? #=> true
|
12
|
+
result.fail? #=> false
|
13
|
+
```
|
14
|
+
|
15
|
+
- One service per action
|
16
|
+
- Service only has one public method `.call` with a hash input argument
|
17
|
+
- The `.call` always return a `State` object. You can ask the state object the execution result
|
6
18
|
|
7
19
|
## Installation
|
8
20
|
|
9
21
|
Install the gem and add to the application's Gemfile by executing:
|
10
22
|
|
11
|
-
|
23
|
+
```bash
|
24
|
+
$ bundle add solidservice
|
25
|
+
```
|
12
26
|
|
13
|
-
|
27
|
+
Or manually add it in Gemfile
|
14
28
|
|
15
|
-
|
29
|
+
```ruby
|
30
|
+
gem 'solidservice'
|
31
|
+
```
|
16
32
|
|
17
|
-
## Usage
|
18
33
|
|
19
|
-
|
34
|
+
## Basic Usage
|
20
35
|
|
21
|
-
|
36
|
+
Here is an example for Rails app.
|
37
|
+
|
38
|
+
1. Create a `services` folder
|
39
|
+
|
40
|
+
```bash
|
41
|
+
mkdir app/services
|
42
|
+
```
|
43
|
+
|
44
|
+
2. Create the service you want
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
class UpdateUser < SolidService
|
48
|
+
def call
|
49
|
+
if user.update(user_params)
|
50
|
+
success!(user: user)
|
51
|
+
else
|
52
|
+
fail!(user: user)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def user
|
59
|
+
@user ||= User.find(params[:id])
|
60
|
+
end
|
61
|
+
|
62
|
+
def user_params
|
63
|
+
@user ||= params[:user_params]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
3. Use this service in controller
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
class UsersController < ApplicationController
|
72
|
+
def update
|
73
|
+
result = UpdateUser.call(
|
74
|
+
id: params[:id],
|
75
|
+
user_params: params.require(:user).permit(:email)
|
76
|
+
)
|
77
|
+
|
78
|
+
if result.success?
|
79
|
+
redirect_to root_path
|
80
|
+
else
|
81
|
+
@user = result.user
|
82
|
+
render :edit
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
```
|
87
|
+
|
88
|
+
## Only 4 DSL in the `call` method
|
89
|
+
|
90
|
+
- `success!` - Success the servcie immediately, any code after it won't be execute (Recommend)
|
91
|
+
- `success` - Just update the state to success
|
92
|
+
- `fail!` - Fail the service immediately, any code after it won't be execute (Recommend)
|
93
|
+
- `fail` - Just update the state to fail
|
22
94
|
|
23
|
-
|
95
|
+
## How to return other data
|
96
|
+
|
97
|
+
You can send data with state object like this:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
success!(user: user)
|
101
|
+
success(user: user, item: item)
|
102
|
+
fail!(email: email, error: error)
|
103
|
+
fail(error: error)
|
104
|
+
```
|
105
|
+
|
106
|
+
Then we can get those data on the result:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
result = ExampleService.call
|
110
|
+
result.success? #=> true
|
111
|
+
result.user
|
112
|
+
result.item
|
113
|
+
|
114
|
+
result.success? #=> false
|
115
|
+
result.error
|
116
|
+
result.email
|
117
|
+
```
|
118
|
+
|
119
|
+
## Servcie success by default
|
120
|
+
|
121
|
+
If you don't call above 4 methods, the servcie will be marked as success by default. It's some those service which just want to execute some action and don't want to return any thing.
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
class ACommandService < SolidService
|
125
|
+
def call
|
126
|
+
# Do some actions that don't need to return anything
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
result = ACommandService.call
|
131
|
+
result.success? #=> true
|
132
|
+
```
|
133
|
+
|
134
|
+
## Use service in service with `call!`
|
135
|
+
|
136
|
+
Sometimes, we want to use a service in another service, but don't want to doing `if/else` on the state object everywhere, then we can use `call!` for the inner service. Then the service will raise error on failure.
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
class Action2 < SolidService
|
140
|
+
def call
|
141
|
+
fail!(error: StandardError.new('something wrong'))
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class Action1 < SolidService
|
146
|
+
def call
|
147
|
+
Action2.call!
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
result = Action1.call
|
152
|
+
result.fail? #=> true
|
153
|
+
result.error #=> #<StandardError: something wrong>
|
154
|
+
```
|
155
|
+
|
156
|
+
|
157
|
+
## Development
|
24
158
|
|
25
|
-
|
159
|
+
```bash
|
160
|
+
bundle install
|
161
|
+
meval rake # Run test
|
162
|
+
meval -a rake # Run tests against all Ruby versions and Rails versions
|
163
|
+
```
|
26
164
|
|
27
165
|
## Contributing
|
28
166
|
|
29
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
167
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/hoppergee/solidservice. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/hoppergee/solidservice/blob/master/CODE_OF_CONDUCT.md).
|
30
168
|
|
31
169
|
## License
|
32
170
|
|
@@ -34,4 +172,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
34
172
|
|
35
173
|
## Code of Conduct
|
36
174
|
|
37
|
-
Everyone interacting in the SolidService project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
175
|
+
Everyone interacting in the SolidService project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/hoppergee/solidservice/blob/master/CODE_OF_CONDUCT.md).
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module SolidService
|
2
|
+
class Base
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def call(params={})
|
7
|
+
service = new(params)
|
8
|
+
service.call
|
9
|
+
service.state
|
10
|
+
|
11
|
+
rescue Success
|
12
|
+
service.state
|
13
|
+
|
14
|
+
rescue Failure
|
15
|
+
service.state
|
16
|
+
|
17
|
+
rescue => e
|
18
|
+
service.fail(error: e)
|
19
|
+
service.state
|
20
|
+
end
|
21
|
+
|
22
|
+
def call!(params={})
|
23
|
+
state = call(params)
|
24
|
+
return state unless state.fail?
|
25
|
+
|
26
|
+
if state.error
|
27
|
+
raise state.error
|
28
|
+
else
|
29
|
+
raise Error.new("Service failed", service_result: state)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :params, :state
|
36
|
+
|
37
|
+
def initialize(params)
|
38
|
+
@params = (params || {}).with_indifferent_access
|
39
|
+
@state = State.new(:success)
|
40
|
+
end
|
41
|
+
|
42
|
+
def call
|
43
|
+
raise "Override please"
|
44
|
+
end
|
45
|
+
|
46
|
+
##########
|
47
|
+
# Private
|
48
|
+
##########
|
49
|
+
|
50
|
+
def success!(params={})
|
51
|
+
@state = State.new(:success, params)
|
52
|
+
raise Success.new
|
53
|
+
end
|
54
|
+
|
55
|
+
def fail!(params={})
|
56
|
+
@state = State.new(:fail, params)
|
57
|
+
raise Failure.new
|
58
|
+
end
|
59
|
+
|
60
|
+
def success(params={})
|
61
|
+
@state = State.new(:success, params)
|
62
|
+
end
|
63
|
+
|
64
|
+
def fail(params={})
|
65
|
+
@state = State.new(:fail, params)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SolidService
|
2
|
+
class State
|
3
|
+
def initialize(state = :success, data={})
|
4
|
+
@state = state || :success
|
5
|
+
@_data = (data || {}).with_indifferent_access
|
6
|
+
end
|
7
|
+
|
8
|
+
def success?
|
9
|
+
@state == :success
|
10
|
+
end
|
11
|
+
|
12
|
+
def fail?
|
13
|
+
@state == :fail
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(key)
|
17
|
+
@_data[key]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/solidservice/version.rb
CHANGED
data/lib/solidservice.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "solidservice/version"
|
4
|
+
require "active_support/core_ext/hash/indifferent_access"
|
4
5
|
|
5
6
|
module SolidService
|
6
|
-
|
7
|
-
|
7
|
+
autoload :Error, "solidservice/error"
|
8
|
+
autoload :Failure, "solidservice/failure"
|
9
|
+
autoload :Success, "solidservice/success"
|
10
|
+
|
11
|
+
autoload :State, "solidservice/state"
|
12
|
+
|
13
|
+
autoload :Base, "solidservice/base"
|
8
14
|
end
|
data/matrixeval.yml
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
version: 0.4
|
2
|
+
target: ruby
|
3
|
+
project_name: solidservice
|
4
|
+
parallel_workers: number_of_processors
|
5
|
+
commands:
|
6
|
+
# - ps
|
7
|
+
# - top
|
8
|
+
# - an_additional_command
|
9
|
+
# mounts:
|
10
|
+
# - /a/path/need/to/mount:/a/path/mount/to
|
11
|
+
matrix:
|
12
|
+
ruby:
|
13
|
+
main: true
|
14
|
+
variants:
|
15
|
+
- key: 2.6
|
16
|
+
container:
|
17
|
+
image: ruby:2.6.10
|
18
|
+
- key: 2.7
|
19
|
+
container:
|
20
|
+
image: ruby:2.7.6
|
21
|
+
- key: 3.0
|
22
|
+
container:
|
23
|
+
image: ruby:3.0.4
|
24
|
+
- key: 3.1
|
25
|
+
default: true
|
26
|
+
container:
|
27
|
+
image: ruby:3.1.2
|
28
|
+
# - key: jruby-9.3
|
29
|
+
# container:
|
30
|
+
# image: jruby:9.3
|
31
|
+
# env:
|
32
|
+
# PATH: "/opt/jruby/bin:/app/bin:/bundle/bin:$PATH"
|
33
|
+
# mounts:
|
34
|
+
# - /a/path/need/to/mount:/a/path/mount/to
|
35
|
+
|
36
|
+
rails:
|
37
|
+
variants:
|
38
|
+
- key: 6.0
|
39
|
+
env:
|
40
|
+
RAILS_VERSION: "~> 6.0.0"
|
41
|
+
- key: 6.1
|
42
|
+
env:
|
43
|
+
RAILS_VERSION: "~> 6.1.0"
|
44
|
+
- key: 7.0
|
45
|
+
default: true
|
46
|
+
env:
|
47
|
+
RAILS_VERSION: "~> 7.0.0"
|
48
|
+
# another:
|
49
|
+
# variants:
|
50
|
+
# - key: key1
|
51
|
+
# default: true
|
52
|
+
# env:
|
53
|
+
# ENV_KEY: 1
|
54
|
+
# - key: key2
|
55
|
+
# env:
|
56
|
+
# ENV_KEY: 2
|
57
|
+
|
58
|
+
exclude:
|
59
|
+
- ruby: 2.6
|
60
|
+
rails: 7.0
|
61
|
+
# - ruby: jruby-9.3
|
62
|
+
# rails: 7.0
|
63
|
+
|
64
|
+
docker-compose-extend:
|
65
|
+
# services:
|
66
|
+
# postgres:
|
67
|
+
# image: postgres:12.8
|
68
|
+
# volumes:
|
69
|
+
# - postgres12:/var/lib/postgresql/data
|
70
|
+
# environment:
|
71
|
+
# POSTGRES_HOST_AUTH_METHOD: trust
|
72
|
+
|
73
|
+
# redis:
|
74
|
+
# image: redis:6.2-alpine
|
75
|
+
|
76
|
+
# volumes:
|
77
|
+
# postgres12:
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solidservice
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hopper Gee
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
12
|
-
dependencies:
|
11
|
+
date: 2022-05-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5'
|
13
27
|
description: Service object with a simple API
|
14
28
|
email:
|
15
29
|
- hopper.gee@hey.com
|
@@ -24,7 +38,13 @@ files:
|
|
24
38
|
- README.md
|
25
39
|
- Rakefile
|
26
40
|
- lib/solidservice.rb
|
41
|
+
- lib/solidservice/base.rb
|
42
|
+
- lib/solidservice/error.rb
|
43
|
+
- lib/solidservice/failure.rb
|
44
|
+
- lib/solidservice/state.rb
|
45
|
+
- lib/solidservice/success.rb
|
27
46
|
- lib/solidservice/version.rb
|
47
|
+
- matrixeval.yml
|
28
48
|
homepage: https://github.com/hoppergee/solidservice
|
29
49
|
licenses:
|
30
50
|
- MIT
|