light-services 2.1 → 2.2

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: 1e777268364638a43bc06d7daab56a5cd8a70e302f782df56e657de079c370f9
4
- data.tar.gz: 7b04287f111ded9b9ead0ae46b5c6696fa8f32c8e4c39c6658e6538008c25b51
3
+ metadata.gz: a5ccceda02f284ebdd089f5b2ecc556e5a8cdea068a94d84e0b59d4cebb71d72
4
+ data.tar.gz: dd35a45b128b94f31cbf4b7bd84afce58fe50f416ef235dae181542c478f93de
5
5
  SHA512:
6
- metadata.gz: d88dd74e63c77525cb7d3771133a6afab9303bce64039255ef74d8a8e6104469e90a315e6fa6f917562d8d6f615a65f7d75e51ecfeac278968e373cd6b84f0ec
7
- data.tar.gz: 2e05b2f401f9e7a93a95081e91cc160c923cab2bff2f2f7a3193c114edea26bc8cc624d9fb4d5af27faa1fab474bc3994f9d71bf4884de78ceda16293255fc50
6
+ metadata.gz: 45e62c84a24199d47085e3f6aaddec90612df913ace4a601be57c6cb8d1df473fdd231980de92b3b5f54b1043c5a6583a8fede03d56dfef14f5cca1261dadef2
7
+ data.tar.gz: ed4da976538c4ea372bfc1c8f8c5e137f4c9653a71e47cda425f8e06fe4c7d9d66ff3550cf2e9681aad2623286879bb4ee9d0bb1c0d37a6612c1bc236a0614f5
@@ -1,4 +1,5 @@
1
1
  versions:
2
- - rubocop: "1.63"
3
- - rubocop-rspec: "2.29"
2
+ - rubocop: "1.64"
4
3
  - rubocop-performance: "1.21"
4
+ - rubocop-rake: "0.6"
5
+ - rubocop-rspec: "2.31"
@@ -0,0 +1,11 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "bundler"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
@@ -2,24 +2,24 @@ name: CI
2
2
  on: push
3
3
 
4
4
  jobs:
5
- rubocop:
6
- name: Rubocop
7
- runs-on: ubuntu-latest
8
- steps:
9
- - name: Git Checkout
10
- uses: actions/checkout@v2
11
-
12
- - name: Rubocop
13
- uses: andrewmcodes/rubocop-linter-action@v3.2.0
14
- env:
15
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5
+ # rubocop:
6
+ # name: Rubocop
7
+ # runs-on: ubuntu-latest
8
+ # steps:
9
+ # - name: Git Checkout
10
+ # uses: actions/checkout@v2
11
+ #
12
+ # - name: Rubocop
13
+ # uses: andrewmcodes/rubocop-linter-action@v3.2.0
14
+ # env:
15
+ # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16
16
 
17
17
  rspec:
18
18
  name: RSpec
19
19
  runs-on: ubuntu-latest
20
20
  strategy:
21
21
  matrix:
22
- ruby: [3.0, 3.1, 3.2, head, debug]
22
+ ruby: [3.0, 3.1, 3.2, 3.3, head, debug]
23
23
  steps:
24
24
  - name: Git Checkout
25
25
  uses: actions/checkout@v2
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.3.1
1
+ 3.4.7
data/Gemfile CHANGED
@@ -5,17 +5,17 @@ source "https://rubygems.org"
5
5
  gemspec
6
6
 
7
7
  group :test do
8
- gem "activerecord", "~> 7.0"
9
- gem "database_cleaner-active_record", "~> 2.1"
10
- gem "sqlite3", "~> 1.7"
8
+ gem "activerecord", "~> 8.1"
9
+ gem "database_cleaner-active_record", "~> 2.2"
10
+ gem "sqlite3", "~> 2.8"
11
11
 
12
12
  gem "codecov", "~> 0.6.0"
13
- gem "rake", "~> 13.2"
13
+ gem "rake", "~> 13.3"
14
14
  gem "rspec", "~> 3.13"
15
15
  gem "simplecov", "~> 0.21"
16
16
 
17
- gem "rubocop", "~> 1.64", require: false
18
- gem "rubocop-performance", "~> 1.21", require: false
19
- gem "rubocop-rake", "~> 0.6.0", require: false
20
- gem "rubocop-rspec", "~> 2.30", require: false
17
+ gem "rubocop", "~> 1.81", require: false
18
+ gem "rubocop-performance", "~> 1.26", require: false
19
+ gem "rubocop-rake", "~> 0.7.0", require: false
20
+ gem "rubocop-rspec", "~> 3.8", require: false
21
21
  end
data/Gemfile.lock CHANGED
@@ -1,131 +1,134 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- light-services (2.1)
4
+ light-services (2.2)
5
+ benchmark (>= 0.5)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
9
- activemodel (7.1.3.2)
10
- activesupport (= 7.1.3.2)
11
- activerecord (7.1.3.2)
12
- activemodel (= 7.1.3.2)
13
- activesupport (= 7.1.3.2)
10
+ activemodel (8.1.1)
11
+ activesupport (= 8.1.1)
12
+ activerecord (8.1.1)
13
+ activemodel (= 8.1.1)
14
+ activesupport (= 8.1.1)
14
15
  timeout (>= 0.4.0)
15
- activesupport (7.1.3.2)
16
+ activesupport (8.1.1)
16
17
  base64
17
18
  bigdecimal
18
- concurrent-ruby (~> 1.0, >= 1.0.2)
19
+ concurrent-ruby (~> 1.0, >= 1.3.1)
19
20
  connection_pool (>= 2.2.5)
20
21
  drb
21
22
  i18n (>= 1.6, < 2)
23
+ json
24
+ logger (>= 1.4.2)
22
25
  minitest (>= 5.1)
23
- mutex_m
24
- tzinfo (~> 2.0)
25
- ast (2.4.2)
26
- base64 (0.2.0)
27
- bigdecimal (3.1.7)
26
+ securerandom (>= 0.3)
27
+ tzinfo (~> 2.0, >= 2.0.5)
28
+ uri (>= 0.13.1)
29
+ ast (2.4.3)
30
+ base64 (0.3.0)
31
+ benchmark (0.5.0)
32
+ bigdecimal (3.3.1)
28
33
  codecov (0.6.0)
29
34
  simplecov (>= 0.15, < 0.22)
30
- concurrent-ruby (1.2.3)
31
- connection_pool (2.4.1)
32
- database_cleaner-active_record (2.1.0)
35
+ concurrent-ruby (1.3.5)
36
+ connection_pool (2.5.4)
37
+ database_cleaner-active_record (2.2.2)
33
38
  activerecord (>= 5.a)
34
- database_cleaner-core (~> 2.0.0)
39
+ database_cleaner-core (~> 2.0)
35
40
  database_cleaner-core (2.0.1)
36
- diff-lcs (1.5.1)
37
- docile (1.4.0)
38
- drb (2.2.1)
39
- i18n (1.14.4)
41
+ diff-lcs (1.6.2)
42
+ docile (1.4.1)
43
+ drb (2.2.3)
44
+ i18n (1.14.7)
40
45
  concurrent-ruby (~> 1.0)
41
- json (2.7.2)
42
- language_server-protocol (3.17.0.3)
43
- mini_portile2 (2.8.6)
44
- minitest (5.22.3)
45
- mutex_m (0.2.0)
46
- parallel (1.24.0)
47
- parser (3.3.1.0)
46
+ json (2.16.0)
47
+ language_server-protocol (3.17.0.5)
48
+ lint_roller (1.1.0)
49
+ logger (1.7.0)
50
+ mini_portile2 (2.8.9)
51
+ minitest (5.26.1)
52
+ parallel (1.27.0)
53
+ parser (3.3.10.0)
48
54
  ast (~> 2.4.1)
49
55
  racc
50
- racc (1.7.3)
56
+ prism (1.6.0)
57
+ racc (1.8.1)
51
58
  rainbow (3.1.1)
52
- rake (13.2.1)
53
- regexp_parser (2.9.2)
54
- rexml (3.2.8)
55
- strscan (>= 3.0.9)
56
- rspec (3.13.0)
59
+ rake (13.3.1)
60
+ regexp_parser (2.11.3)
61
+ rspec (3.13.2)
57
62
  rspec-core (~> 3.13.0)
58
63
  rspec-expectations (~> 3.13.0)
59
64
  rspec-mocks (~> 3.13.0)
60
- rspec-core (3.13.0)
65
+ rspec-core (3.13.6)
61
66
  rspec-support (~> 3.13.0)
62
- rspec-expectations (3.13.0)
67
+ rspec-expectations (3.13.5)
63
68
  diff-lcs (>= 1.2.0, < 2.0)
64
69
  rspec-support (~> 3.13.0)
65
- rspec-mocks (3.13.0)
70
+ rspec-mocks (3.13.7)
66
71
  diff-lcs (>= 1.2.0, < 2.0)
67
72
  rspec-support (~> 3.13.0)
68
- rspec-support (3.13.1)
69
- rubocop (1.64.1)
73
+ rspec-support (3.13.6)
74
+ rubocop (1.81.7)
70
75
  json (~> 2.3)
71
- language_server-protocol (>= 3.17.0)
76
+ language_server-protocol (~> 3.17.0.2)
77
+ lint_roller (~> 1.1.0)
72
78
  parallel (~> 1.10)
73
79
  parser (>= 3.3.0.2)
74
80
  rainbow (>= 2.2.2, < 4.0)
75
- regexp_parser (>= 1.8, < 3.0)
76
- rexml (>= 3.2.5, < 4.0)
77
- rubocop-ast (>= 1.31.1, < 2.0)
81
+ regexp_parser (>= 2.9.3, < 3.0)
82
+ rubocop-ast (>= 1.47.1, < 2.0)
78
83
  ruby-progressbar (~> 1.7)
79
- unicode-display_width (>= 2.4.0, < 3.0)
80
- rubocop-ast (1.31.3)
81
- parser (>= 3.3.1.0)
82
- rubocop-capybara (2.20.0)
83
- rubocop (~> 1.41)
84
- rubocop-factory_bot (2.25.1)
85
- rubocop (~> 1.41)
86
- rubocop-performance (1.21.0)
87
- rubocop (>= 1.48.1, < 2.0)
88
- rubocop-ast (>= 1.31.1, < 2.0)
89
- rubocop-rake (0.6.0)
90
- rubocop (~> 1.0)
91
- rubocop-rspec (2.30.0)
92
- rubocop (~> 1.40)
93
- rubocop-capybara (~> 2.17)
94
- rubocop-factory_bot (~> 2.22)
95
- rubocop-rspec_rails (~> 2.28)
96
- rubocop-rspec_rails (2.28.3)
97
- rubocop (~> 1.40)
84
+ unicode-display_width (>= 2.4.0, < 4.0)
85
+ rubocop-ast (1.48.0)
86
+ parser (>= 3.3.7.2)
87
+ prism (~> 1.4)
88
+ rubocop-performance (1.26.1)
89
+ lint_roller (~> 1.1)
90
+ rubocop (>= 1.75.0, < 2.0)
91
+ rubocop-ast (>= 1.47.1, < 2.0)
92
+ rubocop-rake (0.7.1)
93
+ lint_roller (~> 1.1)
94
+ rubocop (>= 1.72.1)
95
+ rubocop-rspec (3.8.0)
96
+ lint_roller (~> 1.1)
97
+ rubocop (~> 1.81)
98
98
  ruby-progressbar (1.13.0)
99
+ securerandom (0.4.1)
99
100
  simplecov (0.21.2)
100
101
  docile (~> 1.1)
101
102
  simplecov-html (~> 0.11)
102
103
  simplecov_json_formatter (~> 0.1)
103
- simplecov-html (0.12.3)
104
+ simplecov-html (0.13.2)
104
105
  simplecov_json_formatter (0.1.4)
105
- sqlite3 (1.7.3)
106
+ sqlite3 (2.8.0)
106
107
  mini_portile2 (~> 2.8.0)
107
- strscan (3.1.0)
108
- timeout (0.4.1)
108
+ timeout (0.4.4)
109
109
  tzinfo (2.0.6)
110
110
  concurrent-ruby (~> 1.0)
111
- unicode-display_width (2.5.0)
111
+ unicode-display_width (3.2.0)
112
+ unicode-emoji (~> 4.1)
113
+ unicode-emoji (4.1.0)
114
+ uri (1.1.1)
112
115
 
113
116
  PLATFORMS
114
117
  ruby
115
118
 
116
119
  DEPENDENCIES
117
- activerecord (~> 7.0)
120
+ activerecord (~> 8.1)
118
121
  codecov (~> 0.6.0)
119
- database_cleaner-active_record (~> 2.1)
122
+ database_cleaner-active_record (~> 2.2)
120
123
  light-services!
121
- rake (~> 13.2)
124
+ rake (~> 13.3)
122
125
  rspec (~> 3.13)
123
- rubocop (~> 1.64)
124
- rubocop-performance (~> 1.21)
125
- rubocop-rake (~> 0.6.0)
126
- rubocop-rspec (~> 2.30)
126
+ rubocop (~> 1.81)
127
+ rubocop-performance (~> 1.26)
128
+ rubocop-rake (~> 0.7.0)
129
+ rubocop-rspec (~> 3.8)
127
130
  simplecov (~> 0.21)
128
- sqlite3 (~> 1.7)
131
+ sqlite3 (~> 2.8)
129
132
 
130
133
  BUNDLED WITH
131
134
  2.5.10
data/README.md CHANGED
@@ -1,326 +1,104 @@
1
1
  # 🚀 Light Services
2
2
 
3
- A streamlined Service Object implementation for Ruby and Rails, tested in multiple SaaS applications with hundreds of service objects. This gem offers a reliable framework for organizing business logic effectively.
3
+ Light Services is a simple yet powerful way to organize your business logic. This Ruby gem helps you build services that are easy to test, maintain, and understand.
4
4
 
5
- ## 👀 Table of Contents
6
- 1. [Simple Example](#simple-example)
7
- 2. [Usage](#usage)
8
- 1. [Arguments](#arguments)
9
- 2. [Steps](#steps)
10
- 3. [Outputs](#outputs)
11
- 4. [Context](#context)
12
- 3. [Complex Example](#complex-example)
13
- 4. [More Examples](#more-examples)
5
+ ![GitHub CI](https://github.com/light-ruby/light-services/actions/workflows/ci.yml/badge.svg)
6
+ [![Codecov](https://codecov.io/gh/light-ruby/light-services/graph/badge.svg?token=IGJNZ2BQ26)](https://codecov.io/gh/light-ruby/light-services)
14
7
 
15
- ## 💪 Features
8
+ ## Features
16
9
 
17
- 1. Ability to define `arguments`, `steps`, and `outputs`
18
- 1. Isolated behavior of each service object
19
- 1. Errors raise to stop processing subsequent steps
20
- 1. Wrapping actions in database transactions
21
- 1. Ability to pass context to child service objects
22
- 1. Framework agnostic
23
- 1. 100% test coverage
24
-
25
- ## Problems
26
-
27
- This gem was initially intended for internal use and has several issues:
28
-
29
- 1. The gem is not well-documented
30
- 1. The code lacks comments
31
-
32
- ## Installation
33
-
34
- Add this line to your application's Gemfile:
35
-
36
- ```ruby
37
- gem "light-services", "~> 2.0"
38
- ```
10
+ - 🧩 **Simple**: Define your service as a class with `arguments`, `steps`, and `outputs`
11
+ - 🎢 **Transactions**: Automatically rollback database changes if any step fails
12
+ - 👵 **Inheritance**: Inherit from other services to reuse logic seamlessly
13
+ - 🚨 **Error Handling**: Collect errors from steps and handle them your way
14
+ - ⛓️ **Context**: Run multiple services sequentially within the same context
15
+ - 🤔 **Framework Agnostic**: Compatible with Rails, Hanami, or any Ruby framework
16
+ - 🏗️ **Modularity**: Isolate and test your services with ease
17
+ - 🐛 **100% Test Coverage**: Bugs are not welcome here!
18
+ - 🛡️ **Battle-Tested**: In production use since 2017
39
19
 
40
20
  ## Simple Example
41
21
 
42
- ### Send Notification
43
-
44
- Create a basic service object that sends a notification to a user.
45
-
46
22
  ```ruby
47
- class User::SendNotification < ApplicationService
23
+ class GreetService < Light::Services::Base
48
24
  # Arguments
49
- arg :user, type: User
50
- arg :text, type: :string
25
+ arg :name
26
+ arg :age
51
27
 
52
28
  # Steps
53
- step :validate_user
54
- step :validate_text
55
- step :send_notification
56
-
29
+ step :build_message
30
+ step :send_message
31
+
57
32
  # Outputs
58
- output :response
33
+ output :message
59
34
 
60
35
  private
61
36
 
62
- def validate_user
63
- return if user.active?
64
-
65
- errors.add(:user, "isn't active")
37
+ def build_message
38
+ self.message = "Hello, #{name}! You are #{age} years old."
66
39
  end
67
40
 
68
- def validate_text
69
- return if text.present?
70
-
71
- errors.add(:text, "must be present")
72
- end
73
-
74
- def send_notification
75
- self.response = ExternalAPI.send_message(...)
76
- rescue ExternalAPI::Error
77
- errors.add(:base, "External API doesn't work")
41
+ def send_message
42
+ # Send logic goes here
78
43
  end
79
44
  end
80
45
  ```
81
46
 
82
- ## Usage
83
-
84
- ### Arguments
47
+ ## Advanced Example
85
48
 
86
- Pass arguments into the service object as shown:
87
-
88
- **How to define arguments:**
89
49
  ```ruby
90
- class User::SendNotification < ApplicationService
91
- # Required argument
92
- arg :user, type: User
93
-
94
- # Optional argument
95
- arg :device, type: Device, optional: true
96
-
97
- # Argument with default value
98
- arg :text, type: :string, default: "Hello, how are you?"
99
-
100
- # Argument with multiple allowed types
101
- arg :retry, type: [TrueClass, FalseClass], default: false
102
-
103
- # Argument which will be automatically passed into child components
104
- arg :provider, type: Provider, context: true
105
- end
106
- ```
107
-
108
- **How to pass arguments from a controller:**
109
- ```ruby
110
- class UsersController
111
- def send_notification
112
- service = User::SendNotification.run(user: User.first, provider: Provider.first)
113
- # ...
114
- end
115
- end
116
- ```
117
-
118
- **Passing arguments and context from parent to child service object:**
119
- ```ruby
120
- class User::Update
50
+ class User::ResetPassword < Light::Services::Base
121
51
  # Arguments
122
- arg :user, type: User, context: true
52
+ arg :user, type: User, optional: true
53
+ arg :email, type: :string, optional: true
54
+ arg :send_email, type: :boolean, default: true
123
55
 
124
56
  # Steps
125
- # ...
126
- step :send_notification
127
-
128
- private
129
-
130
- # ...
131
-
132
- def send_notification
133
- User::SendNotification
134
- .with(self) # Specifies the current service object as parent, passing all context arguments to a child service object
135
- .run(text: "Your profile was updated") # No need to pass `user` as it's a context argument
136
- end
137
- end
138
- ```
139
-
140
- ### Steps
141
-
142
- Steps are a bit more powerful than they appear.
143
-
144
- ```ruby
145
- class User::Charge
146
- # Run step only when condition meets
147
- step :create_payment_account, unless: :payment_account?
148
-
149
- # Run step only when condition meets
150
- step :charge_credit_card, if: :pay_with_credit_card?
151
-
152
- # Run step after other step
153
- step :update_payment_account, after: :create_payment_account
154
-
155
- # Or before
156
- step :save_information, before: :log_action
157
- end
158
- ```
159
-
160
- ### Outputs
161
-
162
- Outputs are straightforward.
163
-
164
- ```ruby
165
- class User::Charge
166
- # Simple output
167
- output :payment
168
-
169
- # Output with initial value
170
- output :items, default: []
171
- end
172
- ```
173
-
174
- ### Context
175
-
176
- The context specifies the relationship between parent and child service objects.
177
-
178
- What the context does:
179
- 1. Tells the parent service object to pass context arguments to a child service object.
180
- 1. Informs the parent service object to also fail when the child service object fails (this is customizable).
181
-
182
- ```ruby
183
- class User::Charge
184
- # Arguments
185
- arg :user, type: User, context: true
186
- arg :cents, type: Integer
187
-
188
- # ...
189
-
190
- private
191
-
192
- # ...
193
-
194
- def send_notification
195
- # Run service object w/o any context
196
- User::SendNotification
197
- .run(user: user, text: "...")
198
-
199
- # Run service object and specify current one as a parent
200
- User::SendNotification
201
- .with(self)
202
- .run(text: "...")
203
-
204
- # Run service object with context but don't load errors from the child service object
205
- service = User::SendNotification
206
- .with(self, load_errors: false)
207
- .run(text: "...")
208
-
209
- if service.failed?
210
- # That's ok. Process it somehow...
211
- end
212
- end
213
- end
214
- ```
215
-
216
- ## Complex Example
217
-
218
- ### Record Creation
219
-
220
- Explore a more intricate example of creating database records.
221
-
222
- **Here is an example of controller (pretty thin, yeah? but we can make it even thinner):**
223
- ```ruby
224
- class ContactsController < ApplicationController
225
- # ...
226
-
227
- def create
228
- service = Contact::Create.run(service_args)
229
-
230
- if service.success?
231
- render locals: { contact: service.contact }, status: :ok
232
- else
233
- render "shared/errors", locals: { service: service }, status: :bad_request
234
- end
235
- end
236
-
237
- # ...
238
- end
239
- ```
240
-
241
- **Then, let's create a service object (no way, it couldn't be so simple):**
242
- ```ruby
243
- class Contact::Create < CreateService
244
- # We create alias just for a better readability
245
- # so that we can call `service.contact` instead of `service.record`
246
- alias contact record
247
-
248
- private
249
-
250
- def filtered_params
251
- params.require(:contact).permit(:name, :phone)
252
- end
253
- end
254
- ```
255
-
256
- **Let's check what logic we put into `CreateService`:**
257
- ```ruby
258
- class CreateService < ApplicationService
259
- # Arguments
260
- arg :attributes, type: Hash, optional: true
57
+ step :validate
58
+ step :find_user, unless: :user?
59
+ step :generate_reset_token
60
+ step :save_reset_token
61
+ step :send_reset_email, if: :send_email?
261
62
 
262
63
  # Outputs
263
- output :record
264
-
265
- # Steps
266
- step :initialize_record
267
- step :assign_attributes
268
- step :authorize
269
- step :validate
270
- step :save_record
64
+ output :user, type: User
65
+ output :reset_token, type: :string
271
66
 
272
67
  private
273
68
 
274
- def initialize_record
275
- self.record = self.class.module_parent.new
276
- end
277
-
278
- def assign_attributes
279
- record.assign_attributes(filtered_params)
69
+ def validate
70
+ errors.add(:base, "user or email is required") if !user? && !email?
280
71
  end
281
72
 
282
- def authorize
283
- return if force || attributes
284
-
285
- # Here is some Pundit logic 👇
286
- authorize!(record, with_action: :create?)
73
+ def find_user
74
+ self.user = User.find_by("LOWER(email) = ?", email.downcase)
75
+ errors.add(:email, "not found") unless user
287
76
  end
288
77
 
289
- def validate
290
- return if record.valid?
291
-
292
- errors.copy_from(record)
78
+ def generate_reset_token
79
+ self.reset_token = SecureRandom.hex(32)
293
80
  end
294
81
 
295
- def save_record
296
- record.save_with!(self)
82
+ def save_reset_token
83
+ user.update!(
84
+ reset_password_token: reset_token,
85
+ reset_password_sent_at: Time.current,
86
+ )
87
+ rescue ActiveRecord::RecordInvalid => e
88
+ errors.from_record(e.record)
297
89
  end
298
90
 
299
- def filtered_params
300
- raise NotImplementedError
91
+ def send_reset_email
92
+ Mailer::SendEmail
93
+ .with(self) # Call sub-service with the same context
94
+ .run(template: :reset_password, user:, reset_token:)
301
95
  end
302
96
  end
303
97
  ```
304
98
 
305
- **Now we can easily reuse all this code and create as many services as we want:**
306
- ```ruby
307
- class Team::Create < CreateService
308
- alias team record
309
-
310
- private
311
-
312
- def filtered_params
313
- params.require(:team).permit(:name)
314
- end
315
- end
316
- ```
317
-
318
- ## More examples
319
-
320
- You can find more examples here:
321
- [https://github.com/light-ruby/light-services/tree/spec/data/services](https://github.com/light-ruby/light-services/tree/v2/spec/data/services)
99
+ ## Documentation
322
100
 
323
- # Happy coding!
101
+ You can find the full documentation at [light-services.kodkod.me](https://light-services.kodkod.me).
324
102
 
325
103
  ## License
326
104
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "benchmark"
4
+
3
5
  require "light/services/message"
4
6
  require "light/services/messages"
5
7
  require "light/services/base_with_context"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Light
4
4
  module Services
5
- VERSION = "2.1"
5
+ VERSION = "2.2"
6
6
  end
7
7
  end
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["Andrew Kodkod"]
9
9
  spec.email = ["andrew@kodkod.me"]
10
10
 
11
- spec.summary = "Streamlined Service Object Implementation for Ruby and Rails"
12
- spec.description = "Streamlined Service Object Implementation for Ruby and Rails"
13
- spec.homepage = "https://github.com/light-ruby/light-services"
11
+ spec.summary = "Robust service architecture for Ruby frameworks"
12
+ spec.description = "Robust service architecture for Ruby frameworks"
13
+ spec.homepage = "https://light-services-docs.vercel.app/"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
16
16
 
@@ -30,4 +30,6 @@ Gem::Specification.new do |spec|
30
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
31
  spec.require_paths = ["lib"]
32
32
  spec.metadata["rubygems_mfa_required"] = "true"
33
+
34
+ spec.add_dependency "benchmark", ">= 0.5"
33
35
  end
metadata CHANGED
@@ -1,16 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: light-services
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.1'
4
+ version: '2.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kodkod
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-06-03 00:00:00.000000000 Z
12
- dependencies: []
13
- description: Streamlined Service Object Implementation for Ruby and Rails
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: benchmark
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0.5'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0.5'
26
+ description: Robust service architecture for Ruby frameworks
14
27
  email:
15
28
  - andrew@kodkod.me
16
29
  executables: []
@@ -18,6 +31,7 @@ extensions: []
18
31
  extra_rdoc_files: []
19
32
  files:
20
33
  - ".github/config/rubocop_linter_action.yml"
34
+ - ".github/dependabot.yml"
21
35
  - ".github/workflows/ci.yml"
22
36
  - ".gitignore"
23
37
  - ".rspec"
@@ -49,16 +63,15 @@ files:
49
63
  - lib/light/services/settings/step.rb
50
64
  - lib/light/services/version.rb
51
65
  - light-services.gemspec
52
- homepage: https://github.com/light-ruby/light-services
66
+ homepage: https://light-services-docs.vercel.app/
53
67
  licenses:
54
68
  - MIT
55
69
  metadata:
56
70
  allowed_push_host: https://rubygems.org
57
- homepage_uri: https://github.com/light-ruby/light-services
71
+ homepage_uri: https://light-services-docs.vercel.app/
58
72
  source_code_uri: https://github.com/light-ruby/light-services
59
73
  changelog_uri: https://github.com/light-ruby/light-services/blob/master/CHANGELOG.md
60
74
  rubygems_mfa_required: 'true'
61
- post_install_message:
62
75
  rdoc_options: []
63
76
  require_paths:
64
77
  - lib
@@ -73,8 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
86
  - !ruby/object:Gem::Version
74
87
  version: '0'
75
88
  requirements: []
76
- rubygems_version: 3.5.9
77
- signing_key:
89
+ rubygems_version: 3.6.9
78
90
  specification_version: 4
79
- summary: Streamlined Service Object Implementation for Ruby and Rails
91
+ summary: Robust service architecture for Ruby frameworks
80
92
  test_files: []