zen-service 2.2.1 → 2.2.3
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 +4 -4
- data/.github/workflows/ci.yml +36 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +98 -0
- data/Gemfile +9 -0
- data/README.md +155 -66
- data/lib/zen/service/plugins/attributes.rb +2 -2
- data/lib/zen/service/plugins/callable.rb +3 -3
- data/lib/zen/service/plugins/pluggable.rb +1 -0
- data/lib/zen/service/version.rb +1 -1
- data/zen-service.gemspec +0 -7
- metadata +6 -88
- /data/{LICENSE.txt → LICENSE} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e345b9c915b5e8c479cfdfc7bf06a949415759d76ae8af425cc054d0265f600f
|
|
4
|
+
data.tar.gz: 9d4167512ce4b33cc5e4d9c4463b1d1e81b6e325f42a62fb88cd3f3bd8bcbfb8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bb8c0682f5329c0f0928de04c4b6d14f0b5e81ed26714a13e8110cd814dd83543ca850b6b06b8d0df30e8737cb931c67854db0e2002d3e4ce4440de584348077
|
|
7
|
+
data.tar.gz: 429d71228e7353b32b36afb0c547a19a11955c3c55b3fac6b4bf1771a9acb44ba7df0410300174c5faa20bdc7054bc06fce3362b355e47106557889efd606cd9
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
ruby-version: ['3.2', '3.3']
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
|
20
|
+
uses: ruby/setup-ruby@v1
|
|
21
|
+
with:
|
|
22
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
23
|
+
bundler-cache: true
|
|
24
|
+
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: bundle exec rspec
|
|
27
|
+
|
|
28
|
+
- name: Upload coverage to Codecov
|
|
29
|
+
if: matrix.ruby-version == '3.3'
|
|
30
|
+
uses: codecov/codecov-action@v4
|
|
31
|
+
with:
|
|
32
|
+
files: ./coverage/coverage.xml
|
|
33
|
+
flags: unittests
|
|
34
|
+
name: codecov-umbrella
|
|
35
|
+
fail_ci_if_error: false
|
|
36
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [2.2.3] - 2026-01-19
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fix block passing when calling service using `.call` and `.[]` class methods
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Add CI workflow with GitHub Actions
|
|
17
|
+
- Add SimpleCov integration with 100% test coverage (line and branch coverage)
|
|
18
|
+
- Update README with comprehensive documentation, shield badges, and improved examples
|
|
19
|
+
|
|
20
|
+
## [2.2.2] - 2025-12-30
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Fix re-using plugin by inherited service classes
|
|
25
|
+
|
|
26
|
+
## [2.2.1] - 2025-12-29
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Fix plugin reflection options and configuration check
|
|
31
|
+
|
|
32
|
+
## [2.2.0] - 2025-12-28
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- Allow registering plugins with class names (strings) instead of requiring class constants
|
|
37
|
+
- Useful when autoload isn't available yet, e.g., during Rails initialization
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- Update README with improved documentation
|
|
42
|
+
|
|
43
|
+
## [2.1.0] - 2025-12-20
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- Add `:call_unless_called` option to `:persisted_result` plugin
|
|
48
|
+
- When set to `true`, accessing `service.result` will automatically call `#call` if not yet called
|
|
49
|
+
- Default value is `false`
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- Allow plugin re-registration with updated configuration
|
|
54
|
+
- Code cleanup and refactoring
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- Drop obsolete statements from codebase
|
|
59
|
+
|
|
60
|
+
## [2.0.0] - 2025-12-06
|
|
61
|
+
|
|
62
|
+
### Breaking Changes
|
|
63
|
+
|
|
64
|
+
- Complete rewrite focused on simplicity and extensibility
|
|
65
|
+
- Drop majority of built-in plugins from v1.x
|
|
66
|
+
- New plugin API based on `Zen::Service::Plugins::Plugin`
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
|
|
70
|
+
- New core plugin architecture where even fundamental features are plugins
|
|
71
|
+
- `:callable` - Provides `.call` and `.[]` class methods
|
|
72
|
+
- `:attributes` - Manages service initialization parameters with runtime validation
|
|
73
|
+
- `:persisted_result` plugin - Provides `#result` method and `#called?` helper
|
|
74
|
+
- `:result_yielding` plugin - Enables nested service calls to return block-provided values
|
|
75
|
+
- Plugin lifecycle with `used` and `configure` callbacks
|
|
76
|
+
- Plugin inheritance and reconfiguration support
|
|
77
|
+
- Automatic plugin registration for modules extending `Plugin`
|
|
78
|
+
- Manual plugin registration via `Zen::Service::Plugins.register`
|
|
79
|
+
|
|
80
|
+
### Changed
|
|
81
|
+
|
|
82
|
+
3]: https://github.com/akuzko/zen-service/compare/v2.2.2...v2.2.3
|
|
83
|
+
[2.2.
|
|
84
|
+
|
|
85
|
+
- Simplified service object pattern focusing on essential functionality
|
|
86
|
+
- Improved plugin DSL with `register_as`, `default_options`, and `service_extension`
|
|
87
|
+
- Complete README rewrite with comprehensive examples
|
|
88
|
+
|
|
89
|
+
### Removed
|
|
90
|
+
|
|
91
|
+
- Most built-in plugins from v1.x for simplicity
|
|
92
|
+
- Removed legacy plugin APIs
|
|
93
|
+
|
|
94
|
+
[2.2.2]: https://github.com/akuzko/zen-service/compare/v2.2.1...v2.2.2
|
|
95
|
+
[2.2.1]: https://github.com/akuzko/zen-service/compare/v2.2.0...v2.2.1
|
|
96
|
+
[2.2.0]: https://github.com/akuzko/zen-service/compare/v2.1.0...v2.2.0
|
|
97
|
+
[2.1.0]: https://github.com/akuzko/zen-service/compare/v2.0.0...v2.1.0
|
|
98
|
+
[2.0.0]: https://github.com/akuzko/zen-service/releases/tag/v2.0.0
|
data/Gemfile
CHANGED
|
@@ -4,3 +4,12 @@ source "https://rubygems.org"
|
|
|
4
4
|
|
|
5
5
|
# Specify your gem"s dependencies in zen-service.gemspec
|
|
6
6
|
gemspec
|
|
7
|
+
|
|
8
|
+
gem "pry"
|
|
9
|
+
gem "pry-nav"
|
|
10
|
+
gem "rake", "~> 13.0"
|
|
11
|
+
gem "rspec", "~> 3.0"
|
|
12
|
+
gem "rspec-its", "~> 1.2"
|
|
13
|
+
gem "rubocop", "~> 1.81"
|
|
14
|
+
gem "simplecov"
|
|
15
|
+
gem "simplecov-cobertura"
|
data/README.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Flexible and highly extensible Service Objects for business logic organization.
|
|
4
4
|
|
|
5
|
-
[](https://rubygems.org/gems/zen-service)
|
|
6
|
+
[](https://github.com/akuzko/zen-service/actions/workflows/ci.yml)
|
|
7
|
+
[](https://codecov.io/gh/akuzko/zen-service)
|
|
8
|
+
[](https://www.ruby-lang.org)
|
|
9
|
+
[](LICENSE)
|
|
6
10
|
|
|
7
11
|
## Installation
|
|
8
12
|
|
|
@@ -22,12 +26,12 @@ Or install it yourself as:
|
|
|
22
26
|
|
|
23
27
|
## Usage
|
|
24
28
|
|
|
25
|
-
The
|
|
29
|
+
The most basic usage of `Zen::Service` can be demonstrated with the following example:
|
|
26
30
|
|
|
27
|
-
```
|
|
31
|
+
```ruby
|
|
28
32
|
# app/services/todos/update.rb
|
|
29
33
|
module Todos
|
|
30
|
-
class Update < ApplicationService #
|
|
34
|
+
class Update < ApplicationService # Base class for app services, inherits from Zen::Service
|
|
31
35
|
attributes :todo, :params
|
|
32
36
|
|
|
33
37
|
def call
|
|
@@ -40,7 +44,7 @@ module Todos
|
|
|
40
44
|
end
|
|
41
45
|
end
|
|
42
46
|
|
|
43
|
-
# app/controllers/
|
|
47
|
+
# app/controllers/todos_controller.rb
|
|
44
48
|
class TodosController < ApplicationController
|
|
45
49
|
def update
|
|
46
50
|
case Todos::Update.call(todo, params: todo_params)
|
|
@@ -51,97 +55,129 @@ class TodosController < ApplicationController
|
|
|
51
55
|
end
|
|
52
56
|
```
|
|
53
57
|
|
|
54
|
-
### Service
|
|
58
|
+
### Service Attributes
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
`Zen::Service` instances are initialized with _attributes_. To specify the list of available attributes, use the `attributes`
|
|
61
|
+
class method. All attributes are optional during initialization. You can omit keys and pass attributes as positional
|
|
62
|
+
parameters—they will be assigned in the order they were declared. However, you cannot:
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
to the order they were defined. However, you cannot pass more attributes than declared attributes list, as
|
|
62
|
-
well as cannot pass single attribute multiple times (as parameter and as named attribute) or attributes that
|
|
63
|
-
were not declared with `attributes` class method.
|
|
64
|
+
- Pass more attributes than declared
|
|
65
|
+
- Pass the same attribute multiple times (both as positional and keyword argument)
|
|
66
|
+
- Pass undeclared attributes
|
|
64
67
|
|
|
65
|
-
```
|
|
68
|
+
```ruby
|
|
66
69
|
class MyService < Zen::Service
|
|
67
70
|
attributes :foo, :bar
|
|
68
71
|
|
|
69
72
|
def call
|
|
70
|
-
#
|
|
73
|
+
# Your business logic here
|
|
71
74
|
end
|
|
72
75
|
|
|
73
76
|
def foo
|
|
74
|
-
super || 5
|
|
77
|
+
super || 5 # Provide default value
|
|
75
78
|
end
|
|
76
79
|
end
|
|
77
80
|
|
|
81
|
+
# Different ways to initialize services
|
|
78
82
|
s1 = MyService.new
|
|
79
83
|
s1.foo # => 5
|
|
80
84
|
s1.bar # => nil
|
|
81
85
|
|
|
82
86
|
s2 = MyService.new(6)
|
|
83
87
|
s2.foo # => 6
|
|
88
|
+
s2.bar # => nil
|
|
84
89
|
|
|
85
|
-
s3 =
|
|
90
|
+
s3 = MyService.new(foo: 1, bar: 2)
|
|
86
91
|
s3.foo # => 1
|
|
87
92
|
s3.bar # => 2
|
|
93
|
+
|
|
94
|
+
# Create a new service from an existing one with some attributes changed
|
|
95
|
+
s4 = s3.with_attributes(bar: 3)
|
|
96
|
+
s4.foo # => 1
|
|
97
|
+
s4.bar # => 3
|
|
98
|
+
|
|
99
|
+
# Create a service from another service's attributes
|
|
100
|
+
s5 = MyService.from(s3)
|
|
101
|
+
s5.foo # => 1
|
|
102
|
+
s5.bar # => 2
|
|
88
103
|
```
|
|
89
104
|
|
|
90
105
|
### Service Extensions (Plugins)
|
|
91
106
|
|
|
92
|
-
|
|
107
|
+
`zen-service` is built with extensibility at its core. Even fundamental functionality like callable behavior
|
|
108
|
+
and attributes are implemented as plugins. The base `Zen::Service` class uses two core plugins:
|
|
93
109
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
simplicity.
|
|
110
|
+
- `:callable` - Provides class methods `.call` and `.[]` that instantiate and call the service
|
|
111
|
+
- `:attributes` - Manages service initialization parameters with runtime validation
|
|
97
112
|
|
|
98
|
-
|
|
113
|
+
In addition, `zen-service` provides optional built-in plugins:
|
|
99
114
|
|
|
100
|
-
|
|
101
|
-
method call. Also provides `#called?` helper method. Supports `call_unless_called` option.
|
|
102
|
-
When set to `true`, calling `service.result` method will call `#call` method if it has
|
|
103
|
-
not yet been called. Default value is `false`.
|
|
115
|
+
#### `:persisted_result`
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
|
|
117
|
+
Provides `#result` method that returns the value from the most recent `#call` invocation, along with a
|
|
118
|
+
`#called?` helper method.
|
|
107
119
|
|
|
108
|
-
|
|
109
|
-
def call
|
|
110
|
-
logger.call do # logger uses `:result_yielding` plugin
|
|
111
|
-
todo.update!(params)
|
|
112
|
-
[:ok, todo]
|
|
113
|
-
rescue ActiveRecord::RecordInvalid
|
|
114
|
-
[:error, todo.errors.messages]
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
```
|
|
120
|
+
**Options:**
|
|
118
121
|
|
|
119
|
-
|
|
122
|
+
- `call_unless_called: false` (default) - When `true`, accessing `service.result` will automatically
|
|
123
|
+
call `#call` if it hasn't been called yet.
|
|
120
124
|
|
|
121
|
-
|
|
125
|
+
```ruby
|
|
126
|
+
class MyService < Zen::Service
|
|
127
|
+
use :persisted_result, call_unless_called: true
|
|
122
128
|
|
|
123
|
-
|
|
124
|
-
- If the plugin was already used by an ancestor class, only the `configure` callback is invoked,
|
|
125
|
-
allowing reconfiguration without re-including the module
|
|
129
|
+
attributes :value
|
|
126
130
|
|
|
127
|
-
|
|
131
|
+
def call
|
|
132
|
+
value * 2
|
|
133
|
+
end
|
|
134
|
+
end
|
|
128
135
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
136
|
+
service = MyService.new(5)
|
|
137
|
+
service.called? # => false
|
|
138
|
+
service.result # => 10 (automatically calls #call)
|
|
139
|
+
service.called? # => true
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### `:result_yielding`
|
|
143
|
+
|
|
144
|
+
Enables nested service calls to return block-provided values instead of the nested service's return value.
|
|
145
|
+
Useful for wrapping service calls with cross-cutting concerns like logging or error handling.
|
|
146
|
+
|
|
147
|
+
```ruby
|
|
148
|
+
class Logger < Zen::Service
|
|
149
|
+
use :result_yielding
|
|
150
|
+
|
|
151
|
+
# Will result with value return by `yield` expression
|
|
152
|
+
def call
|
|
153
|
+
Rails.logger.info("Starting operation")
|
|
154
|
+
result = yield
|
|
155
|
+
Rails.logger.info("Operation completed: #{result.inspect}")
|
|
156
|
+
end
|
|
132
157
|
end
|
|
133
158
|
|
|
134
|
-
class
|
|
135
|
-
|
|
159
|
+
class UpdateTodo < Zen::Service
|
|
160
|
+
attributes :todo, :params
|
|
161
|
+
|
|
162
|
+
def call
|
|
163
|
+
Logger.call do
|
|
164
|
+
todo.update!(params)
|
|
165
|
+
[:ok, todo]
|
|
166
|
+
rescue ActiveRecord::RecordInvalid
|
|
167
|
+
[:error, todo.errors.messages]
|
|
168
|
+
end
|
|
169
|
+
end
|
|
136
170
|
end
|
|
137
171
|
```
|
|
138
172
|
|
|
139
|
-
|
|
140
|
-
to camel-case notation (relying on ActiveSupport's core extensions)
|
|
173
|
+
### Creating Custom Plugins
|
|
141
174
|
|
|
142
|
-
|
|
175
|
+
Creating custom plugins is straightforward. Below is an example of a plugin that transforms results to
|
|
176
|
+
camelCase notation (using ActiveSupport's core extensions):
|
|
177
|
+
|
|
178
|
+
```ruby
|
|
143
179
|
module CamelizeResult
|
|
144
|
-
extend Zen::Service::Plugin
|
|
180
|
+
extend Zen::Service::Plugins::Plugin
|
|
145
181
|
|
|
146
182
|
def self.used(service_class)
|
|
147
183
|
service_class.prepend(Extension)
|
|
@@ -149,8 +185,8 @@ module CamelizeResult
|
|
|
149
185
|
|
|
150
186
|
def self.camelize(obj)
|
|
151
187
|
case obj
|
|
152
|
-
when Array then obj.map { camelize(
|
|
153
|
-
when Hash then obj.deep_transform_keys {
|
|
188
|
+
when Array then obj.map { |item| camelize(item) }
|
|
189
|
+
when Hash then obj.deep_transform_keys { |key| key.to_s.camelize(:lower).to_sym }
|
|
154
190
|
else obj
|
|
155
191
|
end
|
|
156
192
|
end
|
|
@@ -161,11 +197,7 @@ module CamelizeResult
|
|
|
161
197
|
end
|
|
162
198
|
end
|
|
163
199
|
end
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
and then
|
|
167
200
|
|
|
168
|
-
```rb
|
|
169
201
|
class Todos::Show < Zen::Service
|
|
170
202
|
attributes :todo
|
|
171
203
|
|
|
@@ -182,22 +214,79 @@ end
|
|
|
182
214
|
Todos::Show[todo] # => { id: 1, isCompleted: true }
|
|
183
215
|
```
|
|
184
216
|
|
|
185
|
-
|
|
186
|
-
`Zen::Service::Plugin` are automatically registered when the module is loaded. Alternatively,
|
|
187
|
-
you can register plugins manually:
|
|
217
|
+
#### Plugin Registration
|
|
188
218
|
|
|
189
|
-
|
|
219
|
+
Plugins that extend `Zen::Service::Plugins::Plugin` are automatically registered when the module is loaded.
|
|
220
|
+
You can also register plugins manually:
|
|
221
|
+
|
|
222
|
+
```ruby
|
|
190
223
|
# Register a plugin module
|
|
191
224
|
Zen::Service::Plugins.register(:my_plugin, MyPlugin)
|
|
192
225
|
|
|
193
|
-
# Register by class name (useful when autoload isn't available yet, e.g., during Rails
|
|
226
|
+
# Register by class name (useful when autoload isn't available yet, e.g., during Rails initialization)
|
|
194
227
|
Zen::Service::Plugins.register(:my_plugin, "MyApp::Services::MyPlugin")
|
|
195
228
|
```
|
|
196
229
|
|
|
230
|
+
#### Plugin Lifecycle
|
|
231
|
+
|
|
232
|
+
When using a plugin on a service class:
|
|
233
|
+
|
|
234
|
+
- **First use**: Both `used` and `configure` callbacks are invoked, and the module is included
|
|
235
|
+
- **Inheritance**: If a plugin was already used by an ancestor class, only `configure` is called,
|
|
236
|
+
allowing reconfiguration without re-including the module
|
|
237
|
+
|
|
238
|
+
This design enables child classes to customize inherited plugin behavior:
|
|
239
|
+
|
|
240
|
+
```ruby
|
|
241
|
+
class BaseService < Zen::Service
|
|
242
|
+
use :persisted_result, call_unless_called: false
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
class ChildService < BaseService
|
|
246
|
+
use :persisted_result, call_unless_called: true # Reconfigures without re-including
|
|
247
|
+
end
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### Plugin DSL
|
|
251
|
+
|
|
252
|
+
Plugins can use several DSL methods when extending `Zen::Service::Plugins::Plugin`:
|
|
253
|
+
|
|
254
|
+
```ruby
|
|
255
|
+
module MyPlugin
|
|
256
|
+
extend Zen::Service::Plugins::Plugin
|
|
257
|
+
|
|
258
|
+
# Override the auto-generated registration name
|
|
259
|
+
register_as :custom_name
|
|
260
|
+
|
|
261
|
+
# Set default options
|
|
262
|
+
default_options foo: 5, bar: false
|
|
263
|
+
|
|
264
|
+
# Called when plugin is first used on a class
|
|
265
|
+
def self.used(service_class, **options, &block)
|
|
266
|
+
# Include/prepend modules, add class methods, etc.
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Called every time the plugin is used (including on child classes)
|
|
270
|
+
def self.configure(service_class, **options, &block)
|
|
271
|
+
# Configure behavior based on options
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Testing
|
|
277
|
+
|
|
278
|
+
The gem has 100% test coverage with both line and branch coverage. To run the test suite:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
bundle exec rspec
|
|
282
|
+
```
|
|
283
|
+
|
|
197
284
|
## Development
|
|
198
285
|
|
|
199
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `
|
|
200
|
-
You can also run `bin/console` for an interactive prompt that
|
|
286
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run
|
|
287
|
+
the tests. You can also run `bin/console` for an interactive prompt that allows you to experiment.
|
|
288
|
+
|
|
289
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
201
290
|
|
|
202
291
|
## Contributing
|
|
203
292
|
|
|
@@ -13,7 +13,7 @@ module Zen
|
|
|
13
13
|
|
|
14
14
|
def initialize_clone(*)
|
|
15
15
|
super
|
|
16
|
-
@attributes = @attributes.dup
|
|
16
|
+
@attributes = @attributes.dup
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def with_attributes(attributes)
|
|
@@ -84,7 +84,7 @@ module Zen
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def from(service)
|
|
87
|
-
new(service.send(:attributes))
|
|
87
|
+
new(**service.send(:attributes))
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
90
|
end
|
|
@@ -5,13 +5,13 @@ module Zen
|
|
|
5
5
|
module Callable
|
|
6
6
|
extend Plugin
|
|
7
7
|
|
|
8
|
-
def call
|
|
8
|
+
def call(&)
|
|
9
9
|
# No-op by default
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
module ClassMethods
|
|
13
|
-
def call(
|
|
14
|
-
new(
|
|
13
|
+
def call(*attrs, &block)
|
|
14
|
+
new(*attrs).call(&block)
|
|
15
15
|
end
|
|
16
16
|
alias [] call
|
|
17
17
|
end
|
data/lib/zen/service/version.rb
CHANGED
data/zen-service.gemspec
CHANGED
|
@@ -27,11 +27,4 @@ Gem::Specification.new do |spec|
|
|
|
27
27
|
spec.bindir = "exe"
|
|
28
28
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
29
29
|
spec.require_paths = ["lib"]
|
|
30
|
-
|
|
31
|
-
spec.add_development_dependency "pry"
|
|
32
|
-
spec.add_development_dependency "pry-nav"
|
|
33
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
|
34
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
|
35
|
-
spec.add_development_dependency "rspec-its", "~> 1.2"
|
|
36
|
-
spec.add_development_dependency "rubocop", "~> 1.81"
|
|
37
30
|
end
|
metadata
CHANGED
|
@@ -1,99 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zen-service
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.2.
|
|
4
|
+
version: 2.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Artem Kuzko
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
-
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: pry
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - ">="
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0'
|
|
20
|
-
type: :development
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - ">="
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0'
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: pry-nav
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - ">="
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0'
|
|
34
|
-
type: :development
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - ">="
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: rake
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - "~>"
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: '13.0'
|
|
48
|
-
type: :development
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - "~>"
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: '13.0'
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: rspec
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '3.0'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '3.0'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: rspec-its
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - "~>"
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: '1.2'
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - "~>"
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: '1.2'
|
|
83
|
-
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: rubocop
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - "~>"
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: '1.81'
|
|
90
|
-
type: :development
|
|
91
|
-
prerelease: false
|
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - "~>"
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: '1.81'
|
|
11
|
+
date: 2026-01-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
97
13
|
description: Flexible and highly extensible Services for business logic organization
|
|
98
14
|
email:
|
|
99
15
|
- a.kuzko@gmail.com
|
|
@@ -102,12 +18,14 @@ extensions: []
|
|
|
102
18
|
extra_rdoc_files: []
|
|
103
19
|
files:
|
|
104
20
|
- ".github/copilot-instructions.md"
|
|
21
|
+
- ".github/workflows/ci.yml"
|
|
105
22
|
- ".gitignore"
|
|
106
23
|
- ".rspec"
|
|
107
24
|
- ".rubocop.yml"
|
|
108
25
|
- ".tool-versions"
|
|
26
|
+
- CHANGELOG.md
|
|
109
27
|
- Gemfile
|
|
110
|
-
- LICENSE
|
|
28
|
+
- LICENSE
|
|
111
29
|
- README.md
|
|
112
30
|
- Rakefile
|
|
113
31
|
- bin/console
|
/data/{LICENSE.txt → LICENSE}
RENAMED
|
File without changes
|