f_service 0.3.0 → 0.4.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 +4 -4
- data/CHANGELOG.md +16 -5
- data/README.md +153 -86
- data/f_service.gemspec +14 -5
- data/lib/f_service/base.rb +0 -92
- data/lib/f_service/result/base.rb +0 -7
- data/lib/f_service/result/failure.rb +0 -6
- data/lib/f_service/result/success.rb +0 -7
- data/lib/f_service/rspec/support/helpers/result.rb +2 -11
- data/lib/f_service/rspec/support/matchers/result.rb +1 -1
- data/lib/f_service/version.rb +1 -1
- metadata +5 -31
- data/.github/.dependabot.yml +0 -8
- data/.github/workflows/tests-and-linter.yml +0 -28
- data/.gitignore +0 -58
- data/.rubocop.yml +0 -33
- data/Gemfile +0 -27
- data/Gemfile.lock +0 -103
- data/Rakefile +0 -11
- data/bin/console +0 -15
- data/bin/setup +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e6e4ea7905315820d4149138a6d0acfbcb013cde481b34cb0cbd95247aef439
|
|
4
|
+
data.tar.gz: 7abcb86eaf3080a9c1e8d6bfaca8b5c8a70a932ba0e57fd55e9bd88f479d538c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 36ec32dab3e5b223996963426298949403bf606fccd1d58c26362d1c38de8e46a5717f4639264709aee03d11b78b960f270e4db3b003f9688b57b2e0456bb958
|
|
7
|
+
data.tar.gz: 42d233650b876ca35f68b99d2985c4044b1e2989779e9817c9ea20677ecd3bf696e2d22bf7c9c0238b1803ccf74501af7e65ff1ccd70c4878b11be941218fba1
|
data/CHANGELOG.md
CHANGED
|
@@ -4,11 +4,22 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
## [0.4.0](https://github.com/Fretadao/f_service/compare/v0.3.1...v0.4.0) (2026-08-19)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### ⚠ BREAKING CHANGES
|
|
11
|
+
|
|
12
|
+
* Failure#then and Success#then were removed; use #and_then, which has always been their alias. Base#success, Base#failure and Base#result were removed; use #Success, #Failure and #Check. Result#type was removed; use #types. The mock_service `type:` argument was removed; use `types:` with an array.
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* remove deprecated Failure#then, Success#then and the 0.2.0 leftovers ([#63](https://github.com/Fretadao/f_service/issues/63)) ([69b4e80](https://github.com/Fretadao/f_service/commit/69b4e8099cfdb9850ecab656779436ac9cf16d09))
|
|
17
|
+
|
|
18
|
+
## 0.3.1
|
|
19
|
+
### Added
|
|
20
|
+
- Drop Support to Ruby 2.6 and 2.7
|
|
21
|
+
- Add Support to Ruby 3.2 and 3.3
|
|
22
|
+
- Changed and_error to use a matcher instead of equality comparation #51
|
|
12
23
|
|
|
13
24
|
## 0.3.0
|
|
14
25
|
### Added
|
data/README.md
CHANGED
|
@@ -23,9 +23,14 @@ It uses the Result monad for handling operations.
|
|
|
23
23
|
|
|
24
24
|
Add this line to your application's Gemfile:
|
|
25
25
|
|
|
26
|
+
<!-- x-release-please-start-version -->
|
|
26
27
|
```ruby
|
|
27
|
-
gem 'f_service'
|
|
28
|
+
gem 'f_service', '~> 0.4.0'
|
|
28
29
|
```
|
|
30
|
+
<!-- x-release-please-end-version -->
|
|
31
|
+
|
|
32
|
+
> The version above is kept current automatically on every release; pin to
|
|
33
|
+
> whichever version you prefer.
|
|
29
34
|
|
|
30
35
|
And then execute:
|
|
31
36
|
|
|
@@ -64,11 +69,12 @@ You can optionally specify a list of types which represents that result and a va
|
|
|
64
69
|
class User::Create < FService::Base
|
|
65
70
|
# ...
|
|
66
71
|
def run
|
|
67
|
-
return Failure(:
|
|
72
|
+
return Failure(:invalid_name, data: { name: ["can't be blank"] }) if @name.nil?
|
|
68
73
|
|
|
69
74
|
user = UserRepository.create(name: @name)
|
|
75
|
+
|
|
70
76
|
if user.save
|
|
71
|
-
Success(:
|
|
77
|
+
Success(:created, data: user)
|
|
72
78
|
else
|
|
73
79
|
Failure(:creation_failed, data: user.errors)
|
|
74
80
|
end
|
|
@@ -78,6 +84,11 @@ end
|
|
|
78
84
|
|
|
79
85
|
> Remember, you **have** to return an `FService::Result` at the end of your services.
|
|
80
86
|
|
|
87
|
+
> Always give your results a type. It says what happened, not just whether it worked, so
|
|
88
|
+
> callers can branch on the reason and a failure is readable in a log without opening the
|
|
89
|
+
> service. Pass the payload in `data:`, including on failures — otherwise `#error` is `nil`
|
|
90
|
+
> and whoever serializes it has nothing to show.
|
|
91
|
+
|
|
81
92
|
### Using your service
|
|
82
93
|
|
|
83
94
|
To run your service, use the method `#call` provided by `FService::Base`. We like to use the [implicit call](https://stackoverflow.com/a/19108981/8650655), but you can use it in the form you like most.
|
|
@@ -112,7 +123,7 @@ class UsersController < BaseController
|
|
|
112
123
|
end
|
|
113
124
|
```
|
|
114
125
|
|
|
115
|
-
> Note that you're not limited to using services inside controllers. They're just PORO's (
|
|
126
|
+
> Note that you're not limited to using services inside controllers. They're just PORO's (Plain Old Ruby Objects), so you can use in controllers, models, etc. (even other services!).
|
|
116
127
|
|
|
117
128
|
### Pattern matching
|
|
118
129
|
|
|
@@ -121,79 +132,77 @@ The code above could be rewritten using the `#on_success` and `#on_failure` hook
|
|
|
121
132
|
```ruby
|
|
122
133
|
class UsersController < BaseController
|
|
123
134
|
def create
|
|
124
|
-
User::Create
|
|
125
|
-
|
|
126
|
-
|
|
135
|
+
User::Create
|
|
136
|
+
.call(user_params)
|
|
137
|
+
.on_success { |user| return json_success(user) }
|
|
138
|
+
.on_failure { |errors| return json_error(errors) }
|
|
127
139
|
end
|
|
128
140
|
end
|
|
129
141
|
```
|
|
130
142
|
|
|
131
|
-
|
|
132
|
-
error.
|
|
143
|
+
> You can ignore any of the callbacks, if you want to.
|
|
133
144
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
User::Create.(user_params)
|
|
138
|
-
.on_success(unhandled: true) { |value| return json_success(value) }
|
|
139
|
-
.on_failure(unhandled: true) { |error| return json_error(error) }
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
```
|
|
145
|
+
Once you start matching specific types (below), a result whose type none of the hooks
|
|
146
|
+
mention falls through untouched. Pass `unhandled: true` to run a callback for exactly those
|
|
147
|
+
leftovers:
|
|
143
148
|
|
|
144
149
|
```ruby
|
|
145
150
|
class UsersController < BaseController
|
|
146
151
|
def create
|
|
147
|
-
User::Create
|
|
148
|
-
|
|
149
|
-
|
|
152
|
+
User::Create
|
|
153
|
+
.call(user_params)
|
|
154
|
+
.on_success(:created) { |user| return json_success(user) }
|
|
155
|
+
.on_failure(unhandled: true) { |errors| return json_error(errors) }
|
|
150
156
|
end
|
|
151
157
|
end
|
|
152
158
|
```
|
|
153
159
|
|
|
154
|
-
> You can ignore any of the callbacks, if you want to.
|
|
155
|
-
|
|
156
160
|
Going further, you can match the Result type, in case you want to handle them differently:
|
|
157
161
|
|
|
158
162
|
```ruby
|
|
159
163
|
class UsersController < BaseController
|
|
160
164
|
def create
|
|
161
|
-
User::Create
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
165
|
+
User::Create
|
|
166
|
+
.call(user_params)
|
|
167
|
+
.on_success(:created) { |user| return json_success(user) }
|
|
168
|
+
.on_failure(:invalid_name) { |errors| return json_error(errors) }
|
|
169
|
+
.on_failure(:creation_failed) do |errors|
|
|
170
|
+
MyLogger.report_failure(errors)
|
|
171
|
+
|
|
172
|
+
return json_error(errors)
|
|
173
|
+
end
|
|
170
174
|
end
|
|
171
175
|
end
|
|
172
176
|
```
|
|
173
177
|
|
|
174
178
|
It's possible to provide multiple types to the hooks too. If the result type matches any of the given types,
|
|
175
|
-
the hook will run.
|
|
179
|
+
the hook will run. Say the service also answers `Success(:already_exists, data: user)` when the
|
|
180
|
+
name is taken — both outcomes are fine for the caller:
|
|
176
181
|
|
|
177
182
|
```ruby
|
|
178
183
|
class UsersController < BaseController
|
|
179
184
|
def create
|
|
180
|
-
User::Create
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
User::Create
|
|
186
|
+
.call(user_params)
|
|
187
|
+
.on_success(:created, :already_exists) { |user| return json_success(user) }
|
|
188
|
+
.on_failure(:invalid_name) { |errors| return json_error(errors) }
|
|
189
|
+
.on_failure(:creation_failed) do |errors|
|
|
190
|
+
MyLogger.report_failure(errors)
|
|
191
|
+
|
|
192
|
+
return json_error(errors)
|
|
193
|
+
end
|
|
188
194
|
end
|
|
189
195
|
end
|
|
190
196
|
```
|
|
191
197
|
|
|
192
|
-
###
|
|
198
|
+
### Type precedence
|
|
193
199
|
|
|
194
|
-
FService matches types from left to right, from more specific to more generic.
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
FService matches the service's types from left to right, from more specific to more generic.
|
|
201
|
+
For example, the following result `Failure(:unprocessable_entity, :client_error, :http_response)` will match in the following order:
|
|
202
|
+
1. `:unprocessable_entity`;
|
|
203
|
+
2. `:client_error`;
|
|
204
|
+
3. `:http_response`;
|
|
205
|
+
4. unmatched block;
|
|
197
206
|
|
|
198
207
|
### Chaining services
|
|
199
208
|
|
|
@@ -203,9 +212,10 @@ If some step fails, it will short circuit the call chain.
|
|
|
203
212
|
```ruby
|
|
204
213
|
class UsersController < BaseController
|
|
205
214
|
def create
|
|
206
|
-
result = User::Create
|
|
207
|
-
|
|
208
|
-
|
|
215
|
+
result = User::Create
|
|
216
|
+
.call(user_params)
|
|
217
|
+
.and_then { |user| User::Login.(user) }
|
|
218
|
+
.and_then { |user| User::SendWelcomeEmail.(user) }
|
|
209
219
|
|
|
210
220
|
if result.successful?
|
|
211
221
|
json_success(result.value)
|
|
@@ -221,17 +231,23 @@ You can use the `.to_proc` method on FService::Base to avoid explicit inputs whe
|
|
|
221
231
|
```ruby
|
|
222
232
|
class UsersController < BaseController
|
|
223
233
|
def create
|
|
224
|
-
result = User::Create
|
|
225
|
-
|
|
226
|
-
|
|
234
|
+
result = User::Create
|
|
235
|
+
.call(user_params)
|
|
236
|
+
.and_then(&User::Login)
|
|
237
|
+
.and_then(&User::SendWelcomeEmail)
|
|
227
238
|
# ...
|
|
228
239
|
end
|
|
229
240
|
end
|
|
230
241
|
```
|
|
231
242
|
|
|
243
|
+
> **Coming from 0.2.x?** `Success#then` and `Failure#then` were deprecated in 0.3.0 and
|
|
244
|
+
> removed in 0.4.0. Use `#and_then`, which has always been their alias and behaves
|
|
245
|
+
> identically. Note that `#then` also exists on every Ruby object since 2.6, so a leftover
|
|
246
|
+
> call does not raise — it silently yields the Result itself instead of its value.
|
|
247
|
+
|
|
232
248
|
### `Check` and `Try`
|
|
233
249
|
|
|
234
|
-
You can use `Check` to
|
|
250
|
+
You can use `Check` to convert a boolean into a Result: truthy values map to `Success`, falsey values to `Failure`.
|
|
235
251
|
|
|
236
252
|
```ruby
|
|
237
253
|
Check(:math_works) { 1 < 2 }
|
|
@@ -245,71 +261,116 @@ Check(:math_works) { 1 > 2 }
|
|
|
245
261
|
using the parameter `catch`.
|
|
246
262
|
|
|
247
263
|
```ruby
|
|
248
|
-
class
|
|
264
|
+
class Number::DrawOdd < FService::Base
|
|
249
265
|
def run
|
|
250
|
-
Try(:
|
|
251
|
-
|
|
252
|
-
raise "Yuck! It's a #{
|
|
266
|
+
Try(:drawn_number) do
|
|
267
|
+
drawn_number = rand(1..10)
|
|
268
|
+
raise "Yuck! It's a #{drawn_number}" if drawn_number.even?
|
|
253
269
|
|
|
254
|
-
|
|
270
|
+
drawn_number
|
|
255
271
|
end
|
|
256
272
|
end
|
|
257
273
|
end
|
|
258
274
|
|
|
259
|
-
|
|
260
|
-
# => #<Success @value=9, @types=[:
|
|
275
|
+
Number::DrawOdd.call
|
|
276
|
+
# => #<Success @value=9, @types=[:drawn_number]>
|
|
261
277
|
|
|
262
|
-
|
|
263
|
-
# => #<Failure @error=#<RuntimeError: Yuck! It's a 4>, @types=[:
|
|
278
|
+
Number::DrawOdd.call
|
|
279
|
+
# => #<Failure @error=#<RuntimeError: Yuck! It's a 4>, @types=[:drawn_number]>
|
|
264
280
|
```
|
|
265
281
|
|
|
266
282
|
## Testing
|
|
267
283
|
|
|
268
|
-
We provide
|
|
284
|
+
We provide helpers and matchers to make it easier to test code involving FService services.
|
|
269
285
|
|
|
270
|
-
To make available
|
|
286
|
+
To make them available, add the following require to `spec/spec_helper.rb` or
|
|
287
|
+
`spec/rails_helper.rb`:
|
|
271
288
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
```rb
|
|
289
|
+
```ruby
|
|
275
290
|
require 'f_service/rspec'
|
|
276
291
|
```
|
|
277
292
|
|
|
278
293
|
### Mocking a result
|
|
279
294
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
295
|
+
`mock_service` stubs the service's `#call` and returns the Result you describe. It is a stub,
|
|
296
|
+
not a message expectation: it does not assert that the service was called, so add your own
|
|
297
|
+
`expect(...).to have_received(:call)` when that is the point of the test.
|
|
283
298
|
|
|
284
|
-
|
|
285
|
-
|
|
299
|
+
```ruby
|
|
300
|
+
mock_service(User::Create)
|
|
301
|
+
# => stubs a successful result, with no types and a nil value
|
|
286
302
|
|
|
287
|
-
mock_service(
|
|
288
|
-
# =>
|
|
303
|
+
mock_service(User::Create, result: :success, types: [:created])
|
|
304
|
+
# => stubs a Success typed :created
|
|
289
305
|
|
|
290
|
-
mock_service(
|
|
291
|
-
# =>
|
|
306
|
+
mock_service(User::Create, result: :success, types: [:created], value: instance_spy(User))
|
|
307
|
+
# => stubs a Success typed :created carrying a value
|
|
292
308
|
|
|
293
|
-
mock_service(
|
|
294
|
-
# =>
|
|
309
|
+
mock_service(User::Create, result: :failure, types: [:invalid_name])
|
|
310
|
+
# => stubs a Failure typed :invalid_name, with a nil error
|
|
295
311
|
|
|
296
|
-
mock_service(
|
|
297
|
-
|
|
312
|
+
mock_service(
|
|
313
|
+
User::Create,
|
|
314
|
+
result: :failure,
|
|
315
|
+
types: [:invalid_name],
|
|
316
|
+
value: { name: ["can't be blank"] }
|
|
317
|
+
)
|
|
318
|
+
# => stubs a Failure typed :invalid_name carrying an error
|
|
319
|
+
```
|
|
298
320
|
|
|
299
|
-
|
|
300
|
-
|
|
321
|
+
> `value:` fills `#value` on a Success and `#error` on a Failure — it is the payload either
|
|
322
|
+
> way. `types:` also accepts a bare symbol, but an array reads consistently. The deprecated
|
|
323
|
+
> singular `type:` argument was removed in 0.4.0.
|
|
324
|
+
|
|
325
|
+
Need the Result object itself rather than a stub — to pass it around in a unit test, say?
|
|
326
|
+
`f_service_result` builds one:
|
|
327
|
+
|
|
328
|
+
```ruby
|
|
329
|
+
result = f_service_result(:failure, { name: ["can't be blank"] }, [:invalid_name])
|
|
330
|
+
# => #<Failure @error={name: ["can't be blank"]}, @types=[:invalid_name]>
|
|
301
331
|
```
|
|
302
332
|
|
|
303
333
|
### Matching a result
|
|
304
334
|
|
|
305
|
-
```
|
|
335
|
+
```ruby
|
|
306
336
|
expect(User::Create.(name: 'Joe')).to have_succeed_with(:created)
|
|
307
337
|
|
|
308
338
|
expect(User::Create.(name: 'Joe')).to have_succeed_with(:created).and_value(an_instance_of(User))
|
|
309
339
|
|
|
310
|
-
expect(User::Create.(name: nil)).to have_failed_with(:
|
|
340
|
+
expect(User::Create.(name: nil)).to have_failed_with(:invalid_name)
|
|
341
|
+
|
|
342
|
+
expect(User::Create.(name: nil))
|
|
343
|
+
.to have_failed_with(:invalid_name).and_error({ name: ["can't be blank"] })
|
|
311
344
|
|
|
312
|
-
expect(User::Create.(name: nil))
|
|
345
|
+
expect(User::Create.(name: nil))
|
|
346
|
+
.to have_failed_with(:invalid_name).and_error(a_hash_including(name: ["can't be blank"]))
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
> The matchers compare the type list for **equality**, not inclusion. A service answering
|
|
350
|
+
> `Success(:created, :persisted)` is matched by `have_succeed_with(:created, :persisted)` —
|
|
351
|
+
> `have_succeed_with(:created)` alone fails. Name every type the result carries.
|
|
352
|
+
|
|
353
|
+
Putting it together, a spec for the service built above:
|
|
354
|
+
|
|
355
|
+
```ruby
|
|
356
|
+
RSpec.describe User::Create do
|
|
357
|
+
subject(:create_user) { described_class.call(name: name) }
|
|
358
|
+
|
|
359
|
+
context 'when the name is given' do
|
|
360
|
+
let(:name) { 'Joe' }
|
|
361
|
+
|
|
362
|
+
it { is_expected.to have_succeed_with(:created).and_value(an_instance_of(User)) }
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
context 'when the name is missing' do
|
|
366
|
+
let(:name) { nil }
|
|
367
|
+
|
|
368
|
+
it 'fails naming the offending attribute' do
|
|
369
|
+
expect(create_user)
|
|
370
|
+
.to have_failed_with(:invalid_name).and_error(a_hash_including(:name))
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
313
374
|
```
|
|
314
375
|
|
|
315
376
|
## API Docs
|
|
@@ -320,11 +381,17 @@ You can access the API docs [here](https://www.rubydoc.info/gems/f_service/).
|
|
|
320
381
|
|
|
321
382
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that allows you to experiment.
|
|
322
383
|
|
|
323
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
384
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
385
|
+
|
|
386
|
+
Releases are automated: the version, the `CHANGELOG.md`, the git tag and the push to
|
|
387
|
+
[rubygems.org](https://rubygems.org) are all derived from
|
|
388
|
+
[Conventional Commits](https://www.conventionalcommits.org/) by release-please. There
|
|
389
|
+
is no version to edit and no release command to run by hand — see
|
|
390
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
324
391
|
|
|
325
392
|
## Contributing
|
|
326
393
|
|
|
327
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/Fretadao/f_service.
|
|
394
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Fretadao/f_service. Read [CONTRIBUTING.md](CONTRIBUTING.md) first — it covers the commit conventions the release automation depends on.
|
|
328
395
|
|
|
329
396
|
## License
|
|
330
397
|
|
data/f_service.gemspec
CHANGED
|
@@ -19,20 +19,29 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
|
|
20
20
|
spec.homepage = 'https://github.com/Fretadao/f_service'
|
|
21
21
|
spec.license = 'MIT'
|
|
22
|
+
spec.required_ruby_version = '>= 3.0.0'
|
|
22
23
|
|
|
23
24
|
spec.metadata['homepage_uri'] = spec.homepage
|
|
24
25
|
spec.metadata['source_code_uri'] = 'https://github.com/Fretadao/f_service'
|
|
25
26
|
spec.metadata['documentation_uri'] = 'https://www.rubydoc.info/gems/f_service'
|
|
26
27
|
spec.metadata['changelog_uri'] = 'https://github.com/Fretadao/f_service/blob/master/CHANGELOG.md'
|
|
27
28
|
|
|
28
|
-
#
|
|
29
|
-
#
|
|
29
|
+
# Ship only what a consumer of the gem needs: the library, the docs and the
|
|
30
|
+
# licence. Everything else tracked in the repository is development tooling and
|
|
31
|
+
# was being packaged until now — CI workflows, git hooks, the Gemfile, and so on.
|
|
32
|
+
development_only = %r{
|
|
33
|
+
^(bin|test|spec|features)/ # console/setup scripts and test suites
|
|
34
|
+
| ^\.git # .gitignore, .github/, .githooks/
|
|
35
|
+
| ^\.rubocop # linter configuration
|
|
36
|
+
| ^(Gemfile|Rakefile) # development entrypoints
|
|
37
|
+
| ^CONTRIBUTING # contributor documentation
|
|
38
|
+
| release-please # release automation configuration
|
|
39
|
+
}x
|
|
40
|
+
|
|
30
41
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
31
|
-
`git ls-files -z`.split("\x0").
|
|
42
|
+
`git ls-files -z`.split("\x0").grep_v(development_only)
|
|
32
43
|
end
|
|
33
44
|
spec.bindir = 'exe'
|
|
34
45
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
35
46
|
spec.require_paths = ['lib']
|
|
36
|
-
|
|
37
|
-
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
38
47
|
end
|
data/lib/f_service/base.rb
CHANGED
|
@@ -78,36 +78,6 @@ module FService
|
|
|
78
78
|
raise NotImplementedError, 'Services must implement #run'
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
# Returns a successful operation.
|
|
82
|
-
# You'll probably want to return this inside {#run}.
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
# @example
|
|
86
|
-
# class User::ValidateAge < FService::Base
|
|
87
|
-
# def initialize(age:)
|
|
88
|
-
# @age = age
|
|
89
|
-
# end
|
|
90
|
-
#
|
|
91
|
-
# def run
|
|
92
|
-
# return failure(status: 'No age given!', data: @age) if age.blank?
|
|
93
|
-
# return failure(status: 'Too young!', data: @age) if age < 18
|
|
94
|
-
#
|
|
95
|
-
# success(status: 'Valid age.', data: @age)
|
|
96
|
-
# end
|
|
97
|
-
# end
|
|
98
|
-
#
|
|
99
|
-
# @deprecated Use {#Success} instead.
|
|
100
|
-
# @return [Result::Success] a successful operation
|
|
101
|
-
def success(data = nil)
|
|
102
|
-
FService.deprecate!(
|
|
103
|
-
name: "#{self.class}##{__method__}",
|
|
104
|
-
alternative: '#Success',
|
|
105
|
-
from: caller[0]
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
Result::Success.new(data)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
81
|
# Returns a successful result.
|
|
112
82
|
# You can optionally specify a list of types and a value for your result.
|
|
113
83
|
# You'll probably want to return this inside {#run}.
|
|
@@ -229,67 +199,5 @@ module FService
|
|
|
229
199
|
rescue *catch => e
|
|
230
200
|
Failure(*types, data: e)
|
|
231
201
|
end
|
|
232
|
-
|
|
233
|
-
# Returns a failed operation.
|
|
234
|
-
# You'll probably want to return this inside {#run}.
|
|
235
|
-
# @example
|
|
236
|
-
# class User::ValidateAge < FService::Base
|
|
237
|
-
# def initialize(age:)
|
|
238
|
-
# @age = age
|
|
239
|
-
# end
|
|
240
|
-
#
|
|
241
|
-
# def run
|
|
242
|
-
# return failure(status: 'No age given!', data: @age) if age.blank?
|
|
243
|
-
# return failure(status: 'Too young!', data: @age) if age < 18
|
|
244
|
-
#
|
|
245
|
-
# success(status: 'Valid age.', data: @age)
|
|
246
|
-
# end
|
|
247
|
-
# end
|
|
248
|
-
#
|
|
249
|
-
# @deprecated Use {#Failure} instead.
|
|
250
|
-
# @return [Result::Failure] a failed operation
|
|
251
|
-
def failure(data = nil)
|
|
252
|
-
FService.deprecate!(
|
|
253
|
-
name: "#{self.class}##{__method__}",
|
|
254
|
-
alternative: '#Failure',
|
|
255
|
-
from: caller[0]
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
Result::Failure.new(data)
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
# Return either {Result::Failure Success} or {Result::Failure Failure}
|
|
262
|
-
# given the condition.
|
|
263
|
-
#
|
|
264
|
-
# @example
|
|
265
|
-
# class YearIsLeap < FService::Base
|
|
266
|
-
# def initialize(year:)
|
|
267
|
-
# @year = year
|
|
268
|
-
# end
|
|
269
|
-
#
|
|
270
|
-
# def run
|
|
271
|
-
# return failure(status: 'No year given!', data: @year) if @year.nil?
|
|
272
|
-
#
|
|
273
|
-
# result(leap?, @year)
|
|
274
|
-
# end
|
|
275
|
-
#
|
|
276
|
-
# private
|
|
277
|
-
#
|
|
278
|
-
# def leap?
|
|
279
|
-
# ((@year % 4).zero? && @year % 100 != 0) || (@year % 400).zero?
|
|
280
|
-
# end
|
|
281
|
-
# end
|
|
282
|
-
#
|
|
283
|
-
# @deprecated Use {#Check} instead.
|
|
284
|
-
# @return [Result::Success, Result::Failure]
|
|
285
|
-
def result(condition, data = nil)
|
|
286
|
-
FService.deprecate!(
|
|
287
|
-
name: "#{self.class}##{__method__}",
|
|
288
|
-
alternative: '#Check',
|
|
289
|
-
from: caller[0]
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
condition ? success(data) : failure(data)
|
|
293
|
-
end
|
|
294
202
|
end
|
|
295
203
|
end
|
|
@@ -22,13 +22,6 @@ module FService
|
|
|
22
22
|
@matching_types = []
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
# Implements old attribute type. Its deprecated in favor of using types.
|
|
26
|
-
def type
|
|
27
|
-
FService.deprecate!(name: "#{self.class}##{__method__}", alternative: '#types', from: caller[0])
|
|
28
|
-
|
|
29
|
-
types.size == 1 ? types.first : Array(@matching_types).first
|
|
30
|
-
end
|
|
31
|
-
|
|
32
25
|
# This hook runs if the result is successful.
|
|
33
26
|
# Can receive one or more types to be checked before running the given block.
|
|
34
27
|
#
|
|
@@ -110,12 +110,6 @@ module FService
|
|
|
110
110
|
self
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
-
# See #and_then
|
|
114
|
-
def then
|
|
115
|
-
FService.deprecate!(name: "#{self.class}##{__method__}", alternative: '#and_then', from: caller[0])
|
|
116
|
-
and_then
|
|
117
|
-
end
|
|
118
|
-
|
|
119
113
|
# Outputs a string representation of the object
|
|
120
114
|
#
|
|
121
115
|
#
|
|
@@ -83,13 +83,6 @@ module FService
|
|
|
83
83
|
yield(*to_ary)
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
# See #and_then
|
|
87
|
-
def then(&block)
|
|
88
|
-
FService.deprecate!(name: "#{self.class}##{__method__}", alternative: '#and_then', from: caller[0])
|
|
89
|
-
|
|
90
|
-
and_then(&block)
|
|
91
|
-
end
|
|
92
|
-
|
|
93
86
|
# Returns itself to the given block.
|
|
94
87
|
# Use this to chain multiple actions or service calls (only valid when they return a Result).
|
|
95
88
|
# It works just like the `.and_then` method, but only runs if service is a Failure.
|
|
@@ -12,17 +12,8 @@ module FServiceResultHelpers
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# Mock a Fservice service call returning a result.
|
|
15
|
-
def mock_service(service, result: :success, value: nil,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if type != :not_passed
|
|
19
|
-
alternative = "mock_service(..., types: [#{type.inspect}])"
|
|
20
|
-
name = 'mock_service'
|
|
21
|
-
FService.deprecate_argument_name(name: name, argument_name: :type, alternative: alternative, from: caller[0])
|
|
22
|
-
result_types = Array(type)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
service_result = f_service_result(result, value, result_types)
|
|
15
|
+
def mock_service(service, result: :success, value: nil, types: [])
|
|
16
|
+
service_result = f_service_result(result, value, Array(types))
|
|
26
17
|
allow(service).to receive(:call).and_return(service_result)
|
|
27
18
|
end
|
|
28
19
|
end
|
|
@@ -6,7 +6,7 @@ RSpec::Matchers.define :have_failed_with do |*expected_types|
|
|
|
6
6
|
match do |actual|
|
|
7
7
|
matched = actual.is_a?(FService::Result::Failure) && actual.types == expected_types
|
|
8
8
|
|
|
9
|
-
matched &&= actual.error
|
|
9
|
+
matched &&= values_match?(@expected_error, actual.error) if defined?(@expected_error)
|
|
10
10
|
|
|
11
11
|
matched
|
|
12
12
|
end
|
data/lib/f_service/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,29 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: f_service
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Fretadao Tech Team
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
-
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: bundler
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '2.0'
|
|
20
|
-
type: :development
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - "~>"
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: '2.0'
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
27
12
|
description: |2
|
|
28
13
|
FService is a small gem that provides a base class for your services (aka operations).
|
|
29
14
|
The goal is to make services simpler, safer and more composable.
|
|
@@ -34,18 +19,9 @@ executables: []
|
|
|
34
19
|
extensions: []
|
|
35
20
|
extra_rdoc_files: []
|
|
36
21
|
files:
|
|
37
|
-
- ".github/.dependabot.yml"
|
|
38
|
-
- ".github/workflows/tests-and-linter.yml"
|
|
39
|
-
- ".gitignore"
|
|
40
|
-
- ".rubocop.yml"
|
|
41
22
|
- CHANGELOG.md
|
|
42
|
-
- Gemfile
|
|
43
|
-
- Gemfile.lock
|
|
44
23
|
- LICENSE
|
|
45
24
|
- README.md
|
|
46
|
-
- Rakefile
|
|
47
|
-
- bin/console
|
|
48
|
-
- bin/setup
|
|
49
25
|
- f_service.gemspec
|
|
50
26
|
- lib/f_service.rb
|
|
51
27
|
- lib/f_service/base.rb
|
|
@@ -69,7 +45,6 @@ metadata:
|
|
|
69
45
|
source_code_uri: https://github.com/Fretadao/f_service
|
|
70
46
|
documentation_uri: https://www.rubydoc.info/gems/f_service
|
|
71
47
|
changelog_uri: https://github.com/Fretadao/f_service/blob/master/CHANGELOG.md
|
|
72
|
-
post_install_message:
|
|
73
48
|
rdoc_options: []
|
|
74
49
|
require_paths:
|
|
75
50
|
- lib
|
|
@@ -77,15 +52,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
77
52
|
requirements:
|
|
78
53
|
- - ">="
|
|
79
54
|
- !ruby/object:Gem::Version
|
|
80
|
-
version:
|
|
55
|
+
version: 3.0.0
|
|
81
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
57
|
requirements:
|
|
83
58
|
- - ">="
|
|
84
59
|
- !ruby/object:Gem::Version
|
|
85
60
|
version: '0'
|
|
86
61
|
requirements: []
|
|
87
|
-
rubygems_version: 3.
|
|
88
|
-
signing_key:
|
|
62
|
+
rubygems_version: 3.6.9
|
|
89
63
|
specification_version: 4
|
|
90
64
|
summary: A small, monad-based service class
|
|
91
65
|
test_files: []
|
data/.github/.dependabot.yml
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
name: Ruby
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [master]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [master]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
build:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
strategy:
|
|
13
|
-
matrix:
|
|
14
|
-
ruby: [2.6, 2.7, 3.0, 3.1]
|
|
15
|
-
|
|
16
|
-
steps:
|
|
17
|
-
- uses: actions/checkout@v2
|
|
18
|
-
- name: Set up Ruby ${{ matrix.ruby }}
|
|
19
|
-
uses: ruby/setup-ruby@v1
|
|
20
|
-
with:
|
|
21
|
-
ruby-version: ${{ matrix.ruby }}
|
|
22
|
-
- name: Build and test with Rake
|
|
23
|
-
run: |
|
|
24
|
-
gem install bundler
|
|
25
|
-
bundle install --jobs 4 --retry 3
|
|
26
|
-
bundle exec rake
|
|
27
|
-
- name: Rubocop Linter Action
|
|
28
|
-
run: bundle exec rubocop --parallel
|
data/.gitignore
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
*.gem
|
|
2
|
-
*.rbc
|
|
3
|
-
/.config
|
|
4
|
-
/coverage/
|
|
5
|
-
/InstalledFiles
|
|
6
|
-
/pkg/
|
|
7
|
-
/spec/reports/
|
|
8
|
-
/spec/examples.txt
|
|
9
|
-
/test/tmp/
|
|
10
|
-
/test/version_tmp/
|
|
11
|
-
/tmp/
|
|
12
|
-
|
|
13
|
-
# Used by dotenv library to load environment variables.
|
|
14
|
-
# .env
|
|
15
|
-
|
|
16
|
-
# Ignore Byebug command history file.
|
|
17
|
-
.byebug_history
|
|
18
|
-
|
|
19
|
-
## Specific to RubyMotion:
|
|
20
|
-
.dat*
|
|
21
|
-
.repl_history
|
|
22
|
-
build/
|
|
23
|
-
*.bridgesupport
|
|
24
|
-
build-iPhoneOS/
|
|
25
|
-
build-iPhoneSimulator/
|
|
26
|
-
|
|
27
|
-
## Specific to RubyMotion (use of CocoaPods):
|
|
28
|
-
#
|
|
29
|
-
# We recommend against adding the Pods directory to your .gitignore. However
|
|
30
|
-
# you should judge for yourself, the pros and cons are mentioned at:
|
|
31
|
-
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
|
32
|
-
#
|
|
33
|
-
# vendor/Pods/
|
|
34
|
-
|
|
35
|
-
## Documentation cache and generated files:
|
|
36
|
-
/.yardoc/
|
|
37
|
-
/_yardoc/
|
|
38
|
-
/doc/
|
|
39
|
-
/rdoc/
|
|
40
|
-
|
|
41
|
-
## Environment normalization:
|
|
42
|
-
/.bundle/
|
|
43
|
-
/vendor/bundle
|
|
44
|
-
/lib/bundler/man/
|
|
45
|
-
|
|
46
|
-
# for a library or gem, you might want to ignore these files since the code is
|
|
47
|
-
# intended to run in multiple environments; otherwise, check them in:
|
|
48
|
-
# Gemfile.lock
|
|
49
|
-
# .ruby-version
|
|
50
|
-
# .ruby-gemset
|
|
51
|
-
|
|
52
|
-
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
|
53
|
-
.rvmrc
|
|
54
|
-
|
|
55
|
-
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
|
56
|
-
# .rubocop-https?--*
|
|
57
|
-
|
|
58
|
-
.rspec_status
|
data/.rubocop.yml
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
require:
|
|
2
|
-
- rubocop-rspec
|
|
3
|
-
|
|
4
|
-
AllCops:
|
|
5
|
-
NewCops: enable
|
|
6
|
-
|
|
7
|
-
Layout/LineLength:
|
|
8
|
-
Max: 120
|
|
9
|
-
|
|
10
|
-
Metrics/BlockLength:
|
|
11
|
-
Exclude:
|
|
12
|
-
- "spec/**/*"
|
|
13
|
-
|
|
14
|
-
Style/DocumentationMethod:
|
|
15
|
-
Enabled: true
|
|
16
|
-
|
|
17
|
-
Naming/MethodName:
|
|
18
|
-
Exclude:
|
|
19
|
-
- lib/f_service/base.rb
|
|
20
|
-
|
|
21
|
-
RSpec/ContextWording:
|
|
22
|
-
Prefixes:
|
|
23
|
-
- and
|
|
24
|
-
- but
|
|
25
|
-
- when
|
|
26
|
-
- with
|
|
27
|
-
- without
|
|
28
|
-
|
|
29
|
-
RSpec/ExampleLength:
|
|
30
|
-
Max: 20
|
|
31
|
-
|
|
32
|
-
RSpec/NestedGroups:
|
|
33
|
-
Enabled: false
|
data/Gemfile
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
source 'https://rubygems.org'
|
|
4
|
-
|
|
5
|
-
# Specify your gem's dependencies in f_service.gemspec
|
|
6
|
-
gemspec
|
|
7
|
-
|
|
8
|
-
group :development, :test do
|
|
9
|
-
gem 'pry'
|
|
10
|
-
gem 'pry-nav'
|
|
11
|
-
gem 'rake', '~> 13.0.0'
|
|
12
|
-
gem 'rubocop', '~> 0.82.0', require: false
|
|
13
|
-
gem 'rubocop-rspec', require: false
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
group :docs do
|
|
17
|
-
gem 'yard'
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
group :optional do
|
|
21
|
-
gem 'solargraph'
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
group :test do
|
|
25
|
-
gem 'rspec', '~> 3.0'
|
|
26
|
-
gem 'simplecov', require: false
|
|
27
|
-
end
|
data/Gemfile.lock
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
f_service (0.3.0)
|
|
5
|
-
|
|
6
|
-
GEM
|
|
7
|
-
remote: https://rubygems.org/
|
|
8
|
-
specs:
|
|
9
|
-
ast (2.4.0)
|
|
10
|
-
backport (1.1.2)
|
|
11
|
-
benchmark (0.1.0)
|
|
12
|
-
coderay (1.1.3)
|
|
13
|
-
diff-lcs (1.3)
|
|
14
|
-
docile (1.3.5)
|
|
15
|
-
e2mmap (0.1.0)
|
|
16
|
-
jaro_winkler (1.5.4)
|
|
17
|
-
maruku (0.7.3)
|
|
18
|
-
method_source (1.0.0)
|
|
19
|
-
mini_portile2 (2.8.1)
|
|
20
|
-
nokogiri (1.14.3)
|
|
21
|
-
mini_portile2 (~> 2.8.0)
|
|
22
|
-
racc (~> 1.4)
|
|
23
|
-
parallel (1.19.1)
|
|
24
|
-
parser (2.7.1.1)
|
|
25
|
-
ast (~> 2.4.0)
|
|
26
|
-
pry (0.14.1)
|
|
27
|
-
coderay (~> 1.1)
|
|
28
|
-
method_source (~> 1.0)
|
|
29
|
-
pry-nav (1.0.0)
|
|
30
|
-
pry (>= 0.9.10, < 0.15)
|
|
31
|
-
racc (1.6.2)
|
|
32
|
-
rainbow (3.0.0)
|
|
33
|
-
rake (13.0.1)
|
|
34
|
-
reverse_markdown (1.4.0)
|
|
35
|
-
nokogiri
|
|
36
|
-
rexml (3.2.5)
|
|
37
|
-
rspec (3.9.0)
|
|
38
|
-
rspec-core (~> 3.9.0)
|
|
39
|
-
rspec-expectations (~> 3.9.0)
|
|
40
|
-
rspec-mocks (~> 3.9.0)
|
|
41
|
-
rspec-core (3.9.1)
|
|
42
|
-
rspec-support (~> 3.9.1)
|
|
43
|
-
rspec-expectations (3.9.1)
|
|
44
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
45
|
-
rspec-support (~> 3.9.0)
|
|
46
|
-
rspec-mocks (3.9.1)
|
|
47
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
48
|
-
rspec-support (~> 3.9.0)
|
|
49
|
-
rspec-support (3.9.2)
|
|
50
|
-
rubocop (0.82.0)
|
|
51
|
-
jaro_winkler (~> 1.5.1)
|
|
52
|
-
parallel (~> 1.10)
|
|
53
|
-
parser (>= 2.7.0.1)
|
|
54
|
-
rainbow (>= 2.2.2, < 4.0)
|
|
55
|
-
rexml
|
|
56
|
-
ruby-progressbar (~> 1.7)
|
|
57
|
-
unicode-display_width (>= 1.4.0, < 2.0)
|
|
58
|
-
rubocop-rspec (1.38.1)
|
|
59
|
-
rubocop (>= 0.68.1)
|
|
60
|
-
ruby-progressbar (1.10.1)
|
|
61
|
-
simplecov (0.21.2)
|
|
62
|
-
docile (~> 1.1)
|
|
63
|
-
simplecov-html (~> 0.11)
|
|
64
|
-
simplecov_json_formatter (~> 0.1)
|
|
65
|
-
simplecov-html (0.12.3)
|
|
66
|
-
simplecov_json_formatter (0.1.2)
|
|
67
|
-
solargraph (0.38.6)
|
|
68
|
-
backport (~> 1.1)
|
|
69
|
-
benchmark
|
|
70
|
-
bundler (>= 1.17.2)
|
|
71
|
-
e2mmap
|
|
72
|
-
jaro_winkler (~> 1.5)
|
|
73
|
-
maruku (~> 0.7, >= 0.7.3)
|
|
74
|
-
nokogiri (~> 1.9, >= 1.9.1)
|
|
75
|
-
parser (~> 2.3)
|
|
76
|
-
reverse_markdown (~> 1.0, >= 1.0.5)
|
|
77
|
-
rubocop (~> 0.52)
|
|
78
|
-
thor (~> 1.0)
|
|
79
|
-
tilt (~> 2.0)
|
|
80
|
-
yard (~> 0.9)
|
|
81
|
-
thor (1.0.1)
|
|
82
|
-
tilt (2.0.10)
|
|
83
|
-
unicode-display_width (1.7.0)
|
|
84
|
-
yard (0.9.24)
|
|
85
|
-
|
|
86
|
-
PLATFORMS
|
|
87
|
-
ruby
|
|
88
|
-
|
|
89
|
-
DEPENDENCIES
|
|
90
|
-
bundler (~> 2.0)
|
|
91
|
-
f_service!
|
|
92
|
-
pry
|
|
93
|
-
pry-nav
|
|
94
|
-
rake (~> 13.0.0)
|
|
95
|
-
rspec (~> 3.0)
|
|
96
|
-
rubocop (~> 0.82.0)
|
|
97
|
-
rubocop-rspec
|
|
98
|
-
simplecov
|
|
99
|
-
solargraph
|
|
100
|
-
yard
|
|
101
|
-
|
|
102
|
-
BUNDLED WITH
|
|
103
|
-
2.2.32
|
data/Rakefile
DELETED
data/bin/console
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require 'bundler/setup'
|
|
5
|
-
require 'f_service'
|
|
6
|
-
|
|
7
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
|
-
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
-
|
|
10
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
11
|
-
# require "pry"
|
|
12
|
-
# Pry.start
|
|
13
|
-
|
|
14
|
-
require 'irb'
|
|
15
|
-
IRB.start(__FILE__)
|