verbalize 2.0.1 → 2.3.1
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 +5 -5
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/tests.yml +25 -0
- data/CHANGELOG.md +91 -0
- data/Dockerfile +45 -0
- data/README.md +109 -28
- data/bin/console +2 -6
- data/docker-compose.yml +12 -0
- data/lib/verbalize/action.rb +120 -23
- data/lib/verbalize/build.rb +23 -14
- data/lib/verbalize/version.rb +1 -1
- data/verbalize.gemspec +2 -2
- metadata +20 -18
- data/.travis.yml +0 -4
- data/circle.yml +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b4ab48694dce4b9810ed7289498ee4ff0533919ed08041d5abfa4dda1a3800a7
|
4
|
+
data.tar.gz: e2a160824182fef4e702a65b27116505f492cf5f02022bfe928198bb822b2aae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a533db1a4cc25d45a4c5474a96671d3f172f1e84e7c6bf574f2d281caebbce7967d61f96106a9582cdb3915d4d24c6d4ae33b39577734723b65e0ea4ffcab8d0
|
7
|
+
data.tar.gz: 9068fc27d208da171b89f173eec3af2d78b3a3d90bdc589ec737cf97a978c9044b22a7cc4a8b57237149562169859f819bfce672a65a94978ecaa227a216d907
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: Tests
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
strategy:
|
14
|
+
matrix:
|
15
|
+
ruby-version: ['2.6', '2.7', '3.0']
|
16
|
+
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v2
|
19
|
+
- name: Set up Ruby
|
20
|
+
uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ${{ matrix.ruby-version }}
|
23
|
+
bundler-cache: true
|
24
|
+
- name: Run tests
|
25
|
+
run: bundle exec rspec
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
|
+
|
7
|
+
## 2.3.1 - 2021-06-02
|
8
|
+
### Added
|
9
|
+
- release documentation
|
10
|
+
- ruby 2.7 compatibility to remove deprecation warnings
|
11
|
+
|
12
|
+
## 2.3.0 - 2019-09-23
|
13
|
+
### Added
|
14
|
+
- you can now specify `validates :key { |value| ... }` on actions to run validation on the input
|
15
|
+
*before* running the `call` block.
|
16
|
+
|
17
|
+
## 2.2.0 - 2017-08-19
|
18
|
+
### Added
|
19
|
+
- changelog started
|
20
|
+
- You can now specify default values for optional inputs in the `input` call.
|
21
|
+
Use a regular value to load it once, at load-time, and a lambda to lazily load
|
22
|
+
the value each time the action is called.
|
23
|
+
### Changed
|
24
|
+
- privatize Action.input. Now that we have Action.inputs, we want to avoid calling Action.input (no s) outside of the action itself
|
25
|
+
|
26
|
+
## 2.1.1 - 2017-02-21
|
27
|
+
### Fixed
|
28
|
+
- ensure Verbalize::Action.optional_input always returns an array
|
29
|
+
|
30
|
+
## 2.1.0 - 2017-02-21
|
31
|
+
### Added
|
32
|
+
- introspect Action input using Action.inputs, Action.required_inputs, and Action.optional_inputs
|
33
|
+
|
34
|
+
## 2.0.2 - 2017-2-21 [YANKED]
|
35
|
+
- new functionality was added, so minor version should have been increased instead of patch
|
36
|
+
|
37
|
+
## 2.0.1 - 2016-12-16
|
38
|
+
### Changed
|
39
|
+
- internal refactoring
|
40
|
+
|
41
|
+
## 2.0.0 - 2016-02-14
|
42
|
+
### Added
|
43
|
+
- execution of action routed through Action#perform to better support stubbing
|
44
|
+
- 100% test coverage!!!
|
45
|
+
### Changed
|
46
|
+
- calling Failure#value now raises an error, use Failure#failure instead? Did this happen in 1.3?
|
47
|
+
### Removed
|
48
|
+
- removes action implementation methods other than #call/#call!
|
49
|
+
|
50
|
+
## 1.4.1 - 2016-12-14
|
51
|
+
### Added
|
52
|
+
- Failure#failure added to replace Failure#value
|
53
|
+
### Changed
|
54
|
+
- Result split into Success/Failure
|
55
|
+
### Deprecated
|
56
|
+
- stop including Verbalize itself, use Verbalize::Action instead
|
57
|
+
- stop using action implementation methods other than #call/#call!
|
58
|
+
- stop using Failure#value, used Failure#failure instead
|
59
|
+
|
60
|
+
## 1.4.0 [YANKED] - 2016-12-14
|
61
|
+
### Fixed
|
62
|
+
- error while uploading to ruby gems, yanked and released v1.4.1
|
63
|
+
|
64
|
+
## 1.3.0 - 2016-11-09
|
65
|
+
### Changed
|
66
|
+
- better failure handling
|
67
|
+
|
68
|
+
## 1.2.0 - 2016-11-07
|
69
|
+
### Added
|
70
|
+
- alias Result.success? to Result.succeeded?
|
71
|
+
- alias Result.failure? to Result.failed?
|
72
|
+
### Changed
|
73
|
+
- Action now implements #to_ary instead of subclassing Array
|
74
|
+
|
75
|
+
## 1.1.2 - 2016-11-07 [YANKED]
|
76
|
+
- new functionality was added, so minor version should have been increased instead of patch
|
77
|
+
|
78
|
+
## 1.1.1 - 2016-08-25
|
79
|
+
### Changed
|
80
|
+
- internal refactoring
|
81
|
+
|
82
|
+
## 1.0.1 - 2016-08-10
|
83
|
+
### Fixed
|
84
|
+
- Use send to call Action#call so that Action#call can be privatized
|
85
|
+
|
86
|
+
## 1.0.0 - 2016-08-09
|
87
|
+
### Added
|
88
|
+
- optional input
|
89
|
+
|
90
|
+
## 0.1.0 - 2016-08-07
|
91
|
+
- initial release
|
data/Dockerfile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
ARG BUNDLER_VERSION=2.0.2
|
2
|
+
ARG RUBY_VERSION=2.7.1
|
3
|
+
ARG APP_ROOT=/gem
|
4
|
+
|
5
|
+
#######################################
|
6
|
+
### Builder
|
7
|
+
FROM ruby:${RUBY_VERSION}-alpine AS build-env
|
8
|
+
|
9
|
+
ARG APP_ROOT
|
10
|
+
|
11
|
+
ENV BUNDLE_APP_CONFIG="$APP_ROOT/.bundle"
|
12
|
+
ARG PACKAGES="curl tzdata less git"
|
13
|
+
RUN mkdir $APP_ROOT
|
14
|
+
WORKDIR $APP_ROOT
|
15
|
+
|
16
|
+
RUN apk update \
|
17
|
+
&& apk upgrade \
|
18
|
+
&& apk add --update --no-cache $PACKAGES
|
19
|
+
|
20
|
+
#######################################
|
21
|
+
### Development
|
22
|
+
FROM build-env AS development
|
23
|
+
|
24
|
+
ARG BUNDLER_VERSION
|
25
|
+
ARG APP_ROOT
|
26
|
+
ENV BUNDLE_APP_CONFIG="$APP_ROOT/.bundle"
|
27
|
+
|
28
|
+
WORKDIR $APP_ROOT
|
29
|
+
|
30
|
+
RUN apk add --update --no-cache \
|
31
|
+
build-base \
|
32
|
+
git \
|
33
|
+
tzdata \
|
34
|
+
less
|
35
|
+
|
36
|
+
RUN gem install bundler:$BUNDLER_VERSION
|
37
|
+
|
38
|
+
COPY . $APP_ROOT
|
39
|
+
|
40
|
+
RUN bundle install -j4 --retry 3 \
|
41
|
+
&& rm -rf /usr/local/bundle/cache/*.gem \
|
42
|
+
&& find /usr/local/bundle/gems/ -name "*.c" -delete \
|
43
|
+
&& find /usr/local/bundle/gems/ -name "*.o" -delete
|
44
|
+
|
45
|
+
|
data/README.md
CHANGED
@@ -53,6 +53,35 @@ Add.call # => [:ok, 42]
|
|
53
53
|
Add.call(a: 660, b: 6) # => [:ok, 666]
|
54
54
|
```
|
55
55
|
|
56
|
+
## Default Values
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
# You can define defaults via key/value pairs, as so:
|
60
|
+
class Add
|
61
|
+
include Verbalize::Action
|
62
|
+
# note that these values are evaluated at load-time as they are not wrapped
|
63
|
+
# in lambdas.
|
64
|
+
input optional: [a: 35, b: 7]
|
65
|
+
def call; a + b; end
|
66
|
+
end
|
67
|
+
|
68
|
+
# default values can be lazily loaded by passing in a lambda, e.g.:
|
69
|
+
|
70
|
+
class Tomorrow
|
71
|
+
include Verbalize::Action
|
72
|
+
input optional: [as_of: -> { Time.now }]
|
73
|
+
def call
|
74
|
+
as_of + 1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
start_time = Tomorrow.call!
|
79
|
+
sleep(1)
|
80
|
+
end_time = Tomorrow.call!
|
81
|
+
end_time - start_time # ~1s; the default is executed each call.
|
82
|
+
```
|
83
|
+
|
84
|
+
|
56
85
|
```ruby
|
57
86
|
class Divide
|
58
87
|
include Verbalize::Action
|
@@ -69,6 +98,52 @@ result = Divide.call(a: 1, b: 0) # => [:error, 'You can’t divide by 0']
|
|
69
98
|
result.failed? # => true
|
70
99
|
```
|
71
100
|
|
101
|
+
### Reflection
|
102
|
+
```ruby
|
103
|
+
class Add
|
104
|
+
include Verbalize::Action
|
105
|
+
|
106
|
+
input :a, :b, optional: [:c, :d]
|
107
|
+
|
108
|
+
def call
|
109
|
+
a + b + c + d
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def c
|
115
|
+
@c ||= 0
|
116
|
+
end
|
117
|
+
|
118
|
+
def d
|
119
|
+
@d ||= 0
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
Add.required_inputs # [:a, :b]
|
124
|
+
Add.optional_inputs # [:c, :d]
|
125
|
+
Add.inputs # [:a, :b, :c, :d]
|
126
|
+
```
|
127
|
+
|
128
|
+
## Validation
|
129
|
+
```ruby
|
130
|
+
class FloatAdd
|
131
|
+
include Verbalize::Action
|
132
|
+
|
133
|
+
input :a, :b
|
134
|
+
validate(:a) { |a| a.is_a?(Float) }
|
135
|
+
validate(:b) { |b| b.is_a?(Float) && b > 10.0 }
|
136
|
+
|
137
|
+
def call
|
138
|
+
a + b
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
FloatAdd.call!(a: 1, b: 1) # fails with Input "a" failed validation!
|
143
|
+
FloatAdd.call!(a: 1.0, b: 1.0) # fails with Input "b" failed validation!
|
144
|
+
FloatAdd.call!(a: 1.0, b: 12.0) # 13.0
|
145
|
+
```
|
146
|
+
|
72
147
|
## Comparison/Benchmark
|
73
148
|
```ruby
|
74
149
|
require 'verbalize'
|
@@ -132,21 +207,21 @@ end
|
|
132
207
|
|
133
208
|
```
|
134
209
|
Warming up --------------------------------------
|
135
|
-
Ruby
|
136
|
-
Verbalize
|
137
|
-
Actionizer
|
138
|
-
Interactor 4.
|
210
|
+
Ruby 63.091k i/100ms
|
211
|
+
Verbalize 40.521k i/100ms
|
212
|
+
Actionizer 5.226k i/100ms
|
213
|
+
Interactor 4.874k i/100ms
|
139
214
|
Calculating -------------------------------------
|
140
|
-
Ruby
|
141
|
-
Verbalize
|
142
|
-
Actionizer
|
143
|
-
Interactor
|
215
|
+
Ruby 751.604k (± 3.0%) i/s - 3.785M in 5.041472s
|
216
|
+
Verbalize 457.598k (± 6.1%) i/s - 2.310M in 5.072488s
|
217
|
+
Actionizer 54.874k (± 3.5%) i/s - 276.978k in 5.054541s
|
218
|
+
Interactor 52.294k (± 3.2%) i/s - 263.196k in 5.038365s
|
144
219
|
|
145
220
|
Comparison:
|
146
|
-
Ruby:
|
147
|
-
Verbalize:
|
148
|
-
Actionizer:
|
149
|
-
Interactor:
|
221
|
+
Ruby: 751604.0 i/s
|
222
|
+
Verbalize: 457597.9 i/s - 1.64x slower
|
223
|
+
Actionizer: 54873.6 i/s - 13.70x slower
|
224
|
+
Interactor: 52293.6 i/s - 14.37x slower
|
150
225
|
|
151
226
|
```
|
152
227
|
|
@@ -155,15 +230,15 @@ Comparison:
|
|
155
230
|
### Happy Path
|
156
231
|
|
157
232
|
When testing positive cases of a `Verbalize::Action`, it is recommended to test using the `call!` class method and
|
158
|
-
assert on the result. This implicitly ensures a successful result, and your tests will fail with a bang! if
|
233
|
+
assert on the result. This implicitly ensures a successful result, and your tests will fail with a bang! if
|
159
234
|
something goes wrong:
|
160
235
|
|
161
236
|
```ruby
|
162
237
|
class MyAction
|
163
238
|
include Verbalize::Action
|
164
|
-
|
239
|
+
|
165
240
|
input :a
|
166
|
-
|
241
|
+
|
167
242
|
def call
|
168
243
|
fail!('#{a} is greater than than 100!') if a >= 100
|
169
244
|
a + 1
|
@@ -178,28 +253,28 @@ end
|
|
178
253
|
|
179
254
|
### Sad Path
|
180
255
|
|
181
|
-
When testing negative cases of a `Verbalize::Action`, it is recommended to test using the `call` non-bang
|
256
|
+
When testing negative cases of a `Verbalize::Action`, it is recommended to test using the `call` non-bang
|
182
257
|
class method which will return a `Verbalize::Failure` on failure.
|
183
258
|
|
184
|
-
Use of `call!` here is not advised as it will result in an exception being thrown. Set assertions on both
|
259
|
+
Use of `call!` here is not advised as it will result in an exception being thrown. Set assertions on both
|
185
260
|
the failure outcome and value:
|
186
261
|
|
187
262
|
```ruby
|
188
263
|
class MyAction
|
189
264
|
include Verbalize::Action
|
190
|
-
|
265
|
+
|
191
266
|
input :a
|
192
|
-
|
267
|
+
|
193
268
|
def call
|
194
269
|
fail!('#{a} is greater than 100!') if a >= 100
|
195
270
|
a + 1
|
196
271
|
end
|
197
272
|
end
|
198
|
-
|
273
|
+
|
199
274
|
# rspec:
|
200
275
|
it 'fails when the input is out of bounds' do
|
201
276
|
result = MyAction.call(a: 1000)
|
202
|
-
|
277
|
+
|
203
278
|
expect(result).to be_failed
|
204
279
|
expect(result.failure).to eq '1000 is greater than 100!'
|
205
280
|
end
|
@@ -208,11 +283,11 @@ end
|
|
208
283
|
### Stubbing Responses
|
209
284
|
|
210
285
|
When unit testing, it may be necessary to stub the responses of Verbalize actions. To correctly stub responses,
|
211
|
-
you should __always__ stub the `MyAction.perform` class method on the action class being stubbed per the
|
286
|
+
you should __always__ stub the `MyAction.perform` class method on the action class being stubbed per the
|
212
287
|
instructions below. __Never__ stub the `call` or `call!` methods directly.
|
213
288
|
|
214
289
|
Stubbing `.perform` will enable `Verbalize` to wrap results correctly for references to either `call` or `call!`.
|
215
|
-
|
290
|
+
|
216
291
|
#### Stubbing Successful Responses
|
217
292
|
|
218
293
|
To simulate a successful response of the `Verbalize::Action` being stubbed, you should stub the `MyAction.perform`
|
@@ -225,7 +300,7 @@ class Foo
|
|
225
300
|
def self.multiply_by(multiple)
|
226
301
|
result = MyAction.call(a: 1)
|
227
302
|
raise "I couldn't do the thing!" if result.failure?
|
228
|
-
|
303
|
+
|
229
304
|
result.value * multiple
|
230
305
|
end
|
231
306
|
end
|
@@ -238,9 +313,9 @@ describe Foo do
|
|
238
313
|
allow(MyAction).to receive(:perform)
|
239
314
|
.with(a: 1)
|
240
315
|
.and_return(123)
|
241
|
-
|
316
|
+
|
242
317
|
result = described_class.multiply_by(100)
|
243
|
-
|
318
|
+
|
244
319
|
expect(result).to eq 12300
|
245
320
|
end
|
246
321
|
end
|
@@ -266,7 +341,7 @@ describe Foo do
|
|
266
341
|
allow(MyAction).to receive(:perform)
|
267
342
|
.with(a: 1)
|
268
343
|
.and_throw(::Verbalize::THROWN_SYMBOL, 'Y U NO!')
|
269
|
-
|
344
|
+
|
270
345
|
expect {
|
271
346
|
described_class.multiply_by(100)
|
272
347
|
}.to raise_error "I couldn't do the thing!"
|
@@ -297,6 +372,13 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
297
372
|
|
298
373
|
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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
299
374
|
|
375
|
+
## Releasing
|
376
|
+
|
377
|
+
- Update CHANGELOG.md, and lib/verbalize/version.rb, commit, and push
|
378
|
+
- [Create a new release on github](https://github.com/taylorzr/verbalize/releases/new)
|
379
|
+
- Build the gem version: `gem build verbalize.gemspec`
|
380
|
+
- Push the gem version to rubygems: `gem push verbalize-<VERSION>.gem`
|
381
|
+
|
300
382
|
## Contributing
|
301
383
|
|
302
384
|
Bug reports and pull requests are welcome on GitHub at https://github.com/taylorzr/verbalize.
|
@@ -305,4 +387,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/taylor
|
|
305
387
|
## License
|
306
388
|
|
307
389
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
308
|
-
|
data/bin/console
CHANGED
@@ -6,9 +6,5 @@ require 'verbalize'
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require 'irb'
|
14
|
-
IRB.start
|
9
|
+
require 'pry'
|
10
|
+
Pry.start
|
data/docker-compose.yml
ADDED
data/lib/verbalize/action.rb
CHANGED
@@ -11,13 +11,64 @@ module Verbalize
|
|
11
11
|
throw(THROWN_SYMBOL, failure_value)
|
12
12
|
end
|
13
13
|
|
14
|
+
def action_inputs
|
15
|
+
self.class.inputs.map { |i| [i, self.send(i)] }.to_h
|
16
|
+
end
|
17
|
+
|
14
18
|
def self.included(target)
|
15
19
|
target.extend ClassMethods
|
16
20
|
end
|
17
21
|
|
22
|
+
private
|
23
|
+
|
24
|
+
def __setup(key, value)
|
25
|
+
is_valid = self.class.input_is_valid?(key, value)
|
26
|
+
local_error = self.class.pop_local_error
|
27
|
+
fail!(local_error) if !is_valid && local_error
|
28
|
+
fail! "Input '#{key}' failed validation!" unless is_valid
|
29
|
+
|
30
|
+
instance_variable_set(:"@#{key}", value)
|
31
|
+
end
|
32
|
+
|
18
33
|
module ClassMethods
|
19
|
-
def
|
20
|
-
|
34
|
+
def required_inputs
|
35
|
+
@required_inputs || []
|
36
|
+
end
|
37
|
+
|
38
|
+
def optional_inputs
|
39
|
+
@optional_inputs || []
|
40
|
+
end
|
41
|
+
|
42
|
+
def default_inputs
|
43
|
+
(@defaults || {}).keys
|
44
|
+
end
|
45
|
+
|
46
|
+
def inputs
|
47
|
+
required_inputs + optional_inputs + default_inputs
|
48
|
+
end
|
49
|
+
|
50
|
+
def defaults
|
51
|
+
@defaults
|
52
|
+
end
|
53
|
+
|
54
|
+
def input_validations
|
55
|
+
@input_validations ||= {}
|
56
|
+
end
|
57
|
+
|
58
|
+
def input_is_valid?(input, value)
|
59
|
+
return true unless input_validations.include?(input.to_sym)
|
60
|
+
|
61
|
+
input_validations[input].call(value) == true
|
62
|
+
rescue => e
|
63
|
+
@local_error = e
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
def pop_local_error
|
68
|
+
return nil unless @local_error
|
69
|
+
@local_error
|
70
|
+
ensure
|
71
|
+
@local_error = nil
|
21
72
|
end
|
22
73
|
|
23
74
|
# Because call/call! are defined when Action.input is called, they would
|
@@ -30,35 +81,81 @@ module Verbalize
|
|
30
81
|
def call!
|
31
82
|
__proxied_call!
|
32
83
|
end
|
84
|
+
alias_method :!, :call!
|
33
85
|
|
34
86
|
private
|
35
87
|
|
36
|
-
def
|
37
|
-
|
88
|
+
def input(*required_keywords, optional: [])
|
89
|
+
@required_inputs = required_keywords
|
90
|
+
optional = Array(optional)
|
91
|
+
@optional_inputs = optional.reject { |kw| kw.is_a?(Hash) }
|
92
|
+
assign_defaults(optional)
|
93
|
+
|
94
|
+
class_eval Build.call(required_inputs, optional_inputs, default_inputs)
|
38
95
|
end
|
39
96
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
# 2. Because #1, meta-programming a simple interface to these proxied
|
45
|
-
# methods is much simpler than meta-programming the full methods
|
46
|
-
def __proxied_call(*args)
|
47
|
-
error = catch(:verbalize_error) do
|
48
|
-
value = perform(*args)
|
49
|
-
return Success.new(value)
|
50
|
-
end
|
97
|
+
def validate(keyword, &block)
|
98
|
+
raise Verbalize::Error, 'Missing block to validate against!' unless block_given?
|
99
|
+
input_validations[keyword.to_sym] = block
|
100
|
+
end
|
51
101
|
|
52
|
-
|
102
|
+
def assign_defaults(optional)
|
103
|
+
@defaults = optional.select { |kw| kw.is_a?(Hash) }.reduce(&:merge)
|
104
|
+
@defaults = (@defaults || {})
|
105
|
+
.map { |k, v| [k, v.respond_to?(:call) ? v : -> { v }] }
|
106
|
+
.to_h
|
53
107
|
end
|
54
108
|
|
55
|
-
|
56
|
-
perform(*args)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
109
|
+
if RUBY_VERSION < "2.7"
|
110
|
+
def perform(*args)
|
111
|
+
new(*args).send(:call)
|
112
|
+
end
|
113
|
+
|
114
|
+
def __proxied_call(*args)
|
115
|
+
error = catch(:verbalize_error) do
|
116
|
+
value = perform(*args)
|
117
|
+
return Success.new(value)
|
118
|
+
end
|
119
|
+
|
120
|
+
Failure.new(error)
|
121
|
+
end
|
122
|
+
|
123
|
+
def __proxied_call!(*args)
|
124
|
+
perform(*args)
|
125
|
+
rescue UncaughtThrowError => uncaught_throw_error
|
126
|
+
fail_value = uncaught_throw_error.value
|
127
|
+
error = Verbalize::Error.new("Unhandled fail! called with: #{fail_value.inspect}.")
|
128
|
+
error.set_backtrace(uncaught_throw_error.backtrace[2..-1])
|
129
|
+
raise error
|
130
|
+
end
|
131
|
+
else
|
132
|
+
def perform(**args)
|
133
|
+
new(**args).send(:call)
|
134
|
+
end
|
135
|
+
|
136
|
+
# We used __proxied_call/__proxied_call! for 2 reasons:
|
137
|
+
# 1. The declaration of call/call! needs to be explicit so that tools
|
138
|
+
# like rspec-mocks can verify the actions keywords actually
|
139
|
+
# exist when stubbing
|
140
|
+
# 2. Because #1, meta-programming a simple interface to these proxied
|
141
|
+
# methods is much simpler than meta-programming the full methods
|
142
|
+
def __proxied_call(**args)
|
143
|
+
error = catch(:verbalize_error) do
|
144
|
+
value = perform(**args)
|
145
|
+
return Success.new(value)
|
146
|
+
end
|
147
|
+
|
148
|
+
Failure.new(error)
|
149
|
+
end
|
150
|
+
|
151
|
+
def __proxied_call!(**args)
|
152
|
+
perform(**args)
|
153
|
+
rescue UncaughtThrowError => uncaught_throw_error
|
154
|
+
fail_value = uncaught_throw_error.value
|
155
|
+
error = Verbalize::Error.new("Unhandled fail! called with: #{fail_value.inspect}.")
|
156
|
+
error.set_backtrace(uncaught_throw_error.backtrace[2..-1])
|
157
|
+
raise error
|
158
|
+
end
|
62
159
|
end
|
63
160
|
end
|
64
161
|
end
|
data/lib/verbalize/build.rb
CHANGED
@@ -1,22 +1,28 @@
|
|
1
1
|
module Verbalize
|
2
2
|
class Build
|
3
|
-
def self.call(required_keywords = [], optional_keywords = [])
|
4
|
-
new(required_keywords, optional_keywords).call
|
3
|
+
def self.call(required_keywords = [], optional_keywords = [], default_keywords = [])
|
4
|
+
new(required_keywords, optional_keywords, default_keywords).call
|
5
5
|
end
|
6
6
|
|
7
|
-
def initialize(required_keywords, optional_keywords)
|
7
|
+
def initialize(required_keywords, optional_keywords, default_keywords)
|
8
8
|
@required_keywords = required_keywords
|
9
9
|
@optional_keywords = optional_keywords
|
10
|
+
@default_keywords = default_keywords
|
10
11
|
end
|
11
12
|
|
12
13
|
def call
|
14
|
+
# We have to re-alias `!` to `call!` here, otherwise it will be pointing
|
15
|
+
# to the original `call!` method
|
13
16
|
<<-CODE
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
class << self
|
18
|
+
def call(#{declaration_arguments_string})
|
19
|
+
__proxied_call(#{forwarding_arguments_string})
|
20
|
+
end
|
17
21
|
|
18
|
-
def
|
19
|
-
|
22
|
+
def call!(#{declaration_arguments_string})
|
23
|
+
__proxied_call!(#{forwarding_arguments_string})
|
24
|
+
end
|
25
|
+
alias_method :!, :call!
|
20
26
|
end
|
21
27
|
|
22
28
|
def initialize(#{declaration_arguments_string})
|
@@ -29,18 +35,19 @@ attr_reader #{attribute_readers_string}
|
|
29
35
|
CODE
|
30
36
|
end
|
31
37
|
|
32
|
-
attr_reader :required_keywords, :optional_keywords
|
38
|
+
attr_reader :required_keywords, :optional_keywords, :default_keywords
|
33
39
|
|
34
40
|
private
|
35
41
|
|
36
42
|
def all_keywords
|
37
|
-
required_keywords + optional_keywords
|
43
|
+
required_keywords + optional_keywords + default_keywords
|
38
44
|
end
|
39
45
|
|
40
46
|
def declaration_arguments_string
|
41
|
-
required_segments
|
42
|
-
optional_segments
|
43
|
-
|
47
|
+
required_segments = required_keywords.map { |kw| "#{kw}:" }
|
48
|
+
optional_segments = optional_keywords.map { |kw| "#{kw}: nil" }
|
49
|
+
default_segments = default_keywords.map { |kw| "#{kw}: self.defaults[:#{kw}].call" }
|
50
|
+
(required_segments + optional_segments + default_segments).join(', ')
|
44
51
|
end
|
45
52
|
|
46
53
|
def forwarding_arguments_string
|
@@ -48,7 +55,9 @@ attr_reader #{attribute_readers_string}
|
|
48
55
|
end
|
49
56
|
|
50
57
|
def initialize_body
|
51
|
-
all_keywords.map
|
58
|
+
all_keywords.map do |keyword|
|
59
|
+
"__setup(:#{keyword}, #{keyword})"
|
60
|
+
end.join("\n ")
|
52
61
|
end
|
53
62
|
|
54
63
|
def attribute_readers_string
|
data/lib/verbalize/version.rb
CHANGED
data/verbalize.gemspec
CHANGED
@@ -21,9 +21,9 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
23
|
spec.add_development_dependency 'bundler'
|
24
|
-
spec.add_development_dependency 'rake'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
25
|
spec.add_development_dependency 'rspec'
|
26
26
|
spec.add_development_dependency 'coveralls'
|
27
|
-
spec.add_development_dependency 'rubocop'
|
27
|
+
spec.add_development_dependency 'rubocop'
|
28
28
|
spec.add_development_dependency 'pry'
|
29
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: verbalize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zach Taylor
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,16 +70,16 @@ dependencies:
|
|
70
70
|
name: rubocop
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0
|
82
|
+
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: pry
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
description:
|
97
|
+
description:
|
98
98
|
email:
|
99
99
|
- taylorzr@gmail.com
|
100
100
|
executables: []
|
@@ -102,17 +102,20 @@ extensions: []
|
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
104
|
- ".codeclimate.yml"
|
105
|
+
- ".github/dependabot.yml"
|
106
|
+
- ".github/workflows/tests.yml"
|
105
107
|
- ".gitignore"
|
106
108
|
- ".rspec"
|
107
109
|
- ".rubocop.yml"
|
108
|
-
-
|
110
|
+
- CHANGELOG.md
|
111
|
+
- Dockerfile
|
109
112
|
- Gemfile
|
110
113
|
- LICENSE.txt
|
111
114
|
- README.md
|
112
115
|
- Rakefile
|
113
116
|
- bin/console
|
114
117
|
- bin/setup
|
115
|
-
-
|
118
|
+
- docker-compose.yml
|
116
119
|
- lib/verbalize.rb
|
117
120
|
- lib/verbalize/action.rb
|
118
121
|
- lib/verbalize/build.rb
|
@@ -126,7 +129,7 @@ homepage: https://github.com/taylorzr/verbalize
|
|
126
129
|
licenses:
|
127
130
|
- MIT
|
128
131
|
metadata: {}
|
129
|
-
post_install_message:
|
132
|
+
post_install_message:
|
130
133
|
rdoc_options: []
|
131
134
|
require_paths:
|
132
135
|
- lib
|
@@ -141,9 +144,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
144
|
- !ruby/object:Gem::Version
|
142
145
|
version: '0'
|
143
146
|
requirements: []
|
144
|
-
|
145
|
-
|
146
|
-
signing_key:
|
147
|
+
rubygems_version: 3.0.3
|
148
|
+
signing_key:
|
147
149
|
specification_version: 4
|
148
150
|
summary: Verb based class pattern
|
149
151
|
test_files: []
|
data/.travis.yml
DELETED
data/circle.yml
DELETED