solidservice 0.1.0 → 1.0.0

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: 7141572a223276cd54f17af3fec910c9ca9f064c4d70beaee5f85c10defe88cb
4
- data.tar.gz: e07fda6b224cac244fb85f44fbf5d10468323a27e0ebf2ffcf5dd4c4b40e31ed
3
+ metadata.gz: 4f392725c3e702c59ac368f8b437d4e16a4485f7326b35b818d38cc1225e8098
4
+ data.tar.gz: d26bab0fb422776548372ed8da261ac18ad0f0040a3d520d48f80bea6866b1fb
5
5
  SHA512:
6
- metadata.gz: 372fefa3c563a54bfbe246142f873dbecab933434ac838e0ac28d1d415226ded0826b34b6572e3ec793a94223489b5d0fe77cdbcaf7e6c5aff2f4094053f17ce
7
- data.tar.gz: 4fd9dfe75a6d5d14abb9561d8fa62091b2cd4f92dd3f8e50b9485601f54280cb7d34e50e75260fb1e4ca9f901eaa1225cb8a9c8f6627085470095cc3493bffee
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
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/solidservice`. To experiment with that code, run `bin/console` for an interactive prompt.
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
- TODO: Delete this and the text above, and describe your gem
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
- $ bundle add solidservice
23
+ ```bash
24
+ $ bundle add solidservice
25
+ ```
12
26
 
13
- If bundler is not being used to manage dependencies, install the gem by executing:
27
+ Or manually add it in Gemfile
14
28
 
15
- $ gem install solidservice
29
+ ```ruby
30
+ gem 'solidservice'
31
+ ```
16
32
 
17
- ## Usage
18
33
 
19
- TODO: Write usage instructions here
34
+ ## Basic Usage
20
35
 
21
- ## Development
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
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
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
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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/[USERNAME]/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/[USERNAME]/solidservice/blob/master/CODE_OF_CONDUCT.md).
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/[USERNAME]/solidservice/blob/master/CODE_OF_CONDUCT.md).
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,10 @@
1
+ module SolidService
2
+ class Error < StandardError
3
+ attr_reader :service_result
4
+
5
+ def initialize(message, params={})
6
+ @service_result = params[:service_result]
7
+ super(message)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ module SolidService
2
+ class Failure < StandardError
3
+ end
4
+ 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
@@ -0,0 +1,4 @@
1
+ module SolidService
2
+ class Success < StandardError
3
+ end
4
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidService
4
- VERSION = "0.1.0"
4
+ VERSION = "1.0.0"
5
5
  end
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
- class Error < StandardError; end
7
- # Your code goes here...
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: 0.1.0
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-04-30 00:00:00.000000000 Z
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