pathway 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +22 -21
- data/lib/pathway/plugins/sequel_models.rb +4 -3
- data/lib/pathway/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4018ba4c006cf059f12c711202755d036b98a5ce
|
4
|
+
data.tar.gz: 43aa4a956c419086daa4f3cb2c090ba59f6d2b66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b78616b14447e8577bec833efbc133badb5dd33f6ea0ac7ed118640efc72e9bb3d2c7eabfc0453dab40197567d609c14b786bc172e9c324b3a7967a58a554e5
|
7
|
+
data.tar.gz: a3603b314011b5650f722e63d5f2d7e744a545f0843936bef536dfd9b3a8aa75871da0d8a3fba043c7e8a3c624ac1dde3dafc0b8026b788f94b2e09ec597d5ab
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## [0.6.2] - 2018-05-19
|
2
|
+
### Changed
|
3
|
+
- Allow `:error_message` option for `sequel_models` plugin to propagate down inherited classes
|
4
|
+
|
1
5
|
## [0.6.1] - 2018-03-16
|
2
6
|
### Changed
|
3
7
|
- Update default error message for `:fetch_model` step, at `sequel_models` plugin, to indicate the model's name
|
data/README.md
CHANGED
@@ -199,26 +199,26 @@ Lets start by showing some actual code:
|
|
199
199
|
```
|
200
200
|
|
201
201
|
To define your `call` method using the DSL just call to `process` and pass a block, inside it the DSL will be available.
|
202
|
-
Each `step` (or `set`) call is referring to a method inside the operation class, superclasses or available through a plugin, these methods will be eventually invoked
|
202
|
+
Each `step` (or `set`) call is referring to a method inside the operation class, superclasses or available through a plugin, these methods will be eventually invoked by `call`.
|
203
203
|
All of the steps constitute the operation use case and follow a series of conventions in order to carry the process state along the execution process.
|
204
204
|
|
205
|
-
When you run the `call` method, the auto-generated code will save the provided argument at the `input` key within the execution state. Subsequent steps will receive this state and will be able to
|
205
|
+
When you run the `call` method, the auto-generated code will save the provided argument at the `input` key within the execution state. Subsequent steps will receive this state and will be able to modify it, setting the result value or auxiliary keys to communicate with the next steps on the execution path.
|
206
206
|
|
207
207
|
Each step (as the operation as whole) can succeed of fail, when the latter happens execution is halted, and the operation `call` method returns immediately.
|
208
208
|
To signal a failure you must return a `failure(...)` or `error(...)` in the same fashion as when defining `call` directly.
|
209
209
|
|
210
210
|
If you return a `success(...)` or anything that's not a failure the execution carries on but the value is ignored. If you want to save the result value, you must use `set` instead of `step` at the process block, that will save your wrapped value, into the key provided at `to:`.
|
211
211
|
Also non-failure return values inside steps are automatically wrapped so you can use `success` for clarity sake but it's optional.
|
212
|
-
If you omit the `to:` keyword argument when defining a `set` step, the result key
|
212
|
+
If you omit the `to:` keyword argument when defining a `set` step, the result key will be used by default, but we'll explain more on that later.
|
213
213
|
|
214
214
|
##### Operation execution state
|
215
215
|
|
216
|
-
In order to operate with the execution state, every step method receives a structure representing the current state. This structure is similar to a `Hash` and responds to its
|
216
|
+
In order to operate with the execution state, every step method receives a structure representing the current state. This structure is similar to a `Hash` and responds to its main methods (`:[]`, `:[]=`, `:fetch`, `:store`, `:include?` and `to_hash`).
|
217
217
|
|
218
|
-
When an operation is executed, before running the first step, an initial state is created by
|
218
|
+
When an operation is executed, before running the first step, an initial state is created by copying all the values from the initialization context (and also including `input`).
|
219
219
|
Note that these values can be replaced on later steps but it won't mutate the context object itself since is always frozen.
|
220
220
|
|
221
|
-
A state object can be splatted on method definition in the same fashion as a `Hash`, allowing to cherry pick the attributes we are interested
|
221
|
+
A state object can be splatted on method definition in the same fashion as a `Hash`, thus, allowing to cherry pick the attributes we are interested on any given step:
|
222
222
|
|
223
223
|
```ruby
|
224
224
|
# ...
|
@@ -229,13 +229,13 @@ A state object can be splatted on method definition in the same fashion as a `Ha
|
|
229
229
|
# ...
|
230
230
|
```
|
231
231
|
|
232
|
-
Note the empty double splat at the end of the parameter list, this Ruby-ism means: grab the mentioned keys and ignore all the rest. If you omit
|
232
|
+
Note the empty double splat at the end of the parameter list, this Ruby-ism means: grab the mentioned keys and ignore all the rest. If you omit the `**` when you have outstanding keys, Ruby's `Hash` destructing will fail.
|
233
233
|
|
234
234
|
##### Successful operation result
|
235
235
|
|
236
236
|
On each step you can access or change the operation result for a successful execution.
|
237
237
|
The value will be stored at one of the attributes within the state.
|
238
|
-
By default the state `:value`
|
238
|
+
By default the state's key `:value` will hold the result, but if you prefer to use another name you can specify it through the `result_at` operation class method.
|
239
239
|
|
240
240
|
##### Full example
|
241
241
|
|
@@ -280,40 +280,41 @@ class CreateNugget < Pathway::Operation
|
|
280
280
|
end
|
281
281
|
```
|
282
282
|
|
283
|
-
|
283
|
+
The example above the operation will produce a nugget (whatever that is...).
|
284
|
+
|
285
|
+
As you can see in the code, we are using the previously mentioned methods to indicate we need a current user to be present on initialization: `context: current_user`, a `call` method (defined by `process do ... end`), and that the result value should be stored at the `:nugget` key (`result_at :nugget`).
|
284
286
|
|
285
287
|
Lets delve into the `process` block: it defines three steps using the `step` method and `create_nugget` using `set`, as we said before, this last step will set the result key (`:nugget`) since the `to:` keyword argument is absent.
|
286
288
|
|
287
289
|
Now, for each of the step methods:
|
288
290
|
|
289
|
-
- `:authorize` doesn't
|
290
|
-
- `:validate` gets the state, checks the validity of the `:input` value which as we said is just the `call` method input, returns an `error(...)` when there's a problem, and if the validation is correct it updates the state but saving the sanitized values in `:params`. Note that the return value is `state[:params]`, but is ignored like
|
291
|
+
- `:authorize` doesn't need the state so just ignores it, then checks if the current user is allowed to perform the operation and halts the execution by returning a `:forbidden` error type if is not, otherwise does nothing and the execution goes on.
|
292
|
+
- `:validate` gets the state, checks the validity of the `:input` value which as we said is just the `call` method input, returns an `error(...)` when there's a problem, and if the validation is correct it updates the state but saving the sanitized values in `:params`. Note that on success the return value is `state[:params]`, but is ignored like on `:authorize`, since this method was also specified using `step`.
|
291
293
|
- `:create_nugget` first takes the `:params` attribute from the state (ignoring everything else), and calls `create` on the `Nugget` model with the sanitized params and the current user. The return value is saved to the result key (`:nugget` in this case) as the step is defined using `step` without `to:`.
|
292
294
|
- `:notify` grabs the `:nugget` from the state, and simply emits a notification with it, it has no meaningful return value, so is ignored.
|
293
295
|
|
294
|
-
This example basically touches all the essential concepts needed for defining an operation class. If you can grasp it you already
|
296
|
+
This example basically touches all the essential concepts needed for defining an operation class. If you can grasp it you've already a good understanding on how to implement one. There are still some very important bits to cover (like testing), and we'll tackle them on later sections.
|
295
297
|
|
296
|
-
On a final note, you may be thinking
|
298
|
+
On a final note, you may be thinking the code could be bit less verbose; also, shouldn't very common stuff like validation or authorization be simpler to use?; and maybe, why specify the result key name?, it could be possible infer it from the surrounding code. We will address all those issues on the next section using plugins, `pathway`'s extension mechanism.
|
297
299
|
|
298
300
|
### Plugins
|
299
301
|
|
300
|
-
Pathway can be extended
|
302
|
+
Pathway operations can be extended with plugins. They are very similar as the ones found in [Roda](http://roda.jeremyevans.net/) or [Sequel](http://sequel.jeremyevans.net/). So if you are already familiar with any of those gems you shouldn't have any problem with `pathway`'s plugin system.
|
301
303
|
|
302
|
-
|
304
|
+
To activate a plugin just call the `plugin` method on the operation class:
|
303
305
|
|
304
306
|
```ruby
|
305
307
|
class BaseOperation < Pathway::Operation
|
306
308
|
plugin :foobar, qux: 'quz'
|
307
309
|
end
|
308
310
|
|
309
|
-
|
310
311
|
class SomeOperation < BaseOperation
|
311
312
|
# The :foobar plugin will also be activated here
|
312
313
|
end
|
313
314
|
```
|
314
315
|
|
315
316
|
The plugin name must be specified as a `Symbol` (or also as the `Module` where is implemented, but more on that later), and can it take parameters next to the plugin's name.
|
316
|
-
When activated it will enrich your operations with new instance and class methods plus
|
317
|
+
When activated it will enrich your operations with new instance and class methods plus extra customs step for the process DSL.
|
317
318
|
|
318
319
|
Mind you, if you wish to activate a plugin for a number of operations you can activate it for all of them directly on the `Pathway::Operation` class, or you can create your own base operation and all its descendants will inherit the base class' plugins.
|
319
320
|
|
@@ -346,7 +347,7 @@ class CreateNugget < Pathway::Operation
|
|
346
347
|
end
|
347
348
|
```
|
348
349
|
|
349
|
-
As it can be seen at the code above, the form is first
|
350
|
+
As it can be seen at the code above, the form is first created elsewhere, then is configured to be used by the operation (by calling `form NuggetForm`), and validate the input at the process block by calling `step :validate`.
|
350
351
|
|
351
352
|
```ruby
|
352
353
|
class CreateNugget < Pathway::Operation
|
@@ -366,7 +367,7 @@ class CreateNugget < Pathway::Operation
|
|
366
367
|
end
|
367
368
|
```
|
368
369
|
|
369
|
-
|
370
|
+
Now, this second example is equivalent to the first one, but here we call `form` with a block instead and no parameter; this block will be use as definition body for a form object that will be stored internally. Thus keeping the form and operation at the same place, this is convenient when you have a rather simpler form and don't need to reuse it.
|
370
371
|
|
371
372
|
One interesting nuance to keep in mind regarding the inline block form is that, when doing operation inheritance, if the parent operation already has a form, the child operation will define a new one extending from the parent's. This is very useful to share form functionality among related operations in the same class hierarchy.
|
372
373
|
|
@@ -399,7 +400,7 @@ class CreateNugget < Pathway::Operation
|
|
399
400
|
end
|
400
401
|
```
|
401
402
|
|
402
|
-
Here
|
403
|
+
Here the defined form needs a `:user_name` option, so we tell the operation to grab the attribute with the same name from the state by activating `:auto_wire_options`, afterwards, when the validation runs, the form will already have the user name available.
|
403
404
|
|
404
405
|
Mind you, this option is `false` by default, so be sure to set it to `true` at `Pathway::Operation` if you'd rather have it for all your operations.
|
405
406
|
|
@@ -417,7 +418,7 @@ class CreateNugget < Pathway::Operation
|
|
417
418
|
end
|
418
419
|
|
419
420
|
process do
|
420
|
-
step :validate, with: { user_name: :current_user_name } # Inject :user_name to the form object
|
421
|
+
step :validate, with: { user_name: :current_user_name } # Inject :user_name to the form object with the state's :current_user_name
|
421
422
|
step :create_nugget
|
422
423
|
end
|
423
424
|
|
@@ -28,13 +28,14 @@ module Pathway
|
|
28
28
|
self.model_class = model_class
|
29
29
|
self.search_field = search_by
|
30
30
|
self.result_key = Inflector.underscore(Inflector.demodulize(model_class.name)).to_sym if set_result_key
|
31
|
-
self.model_not_found = error_message || Inflector.humanize(Inflector.underscore(Inflector.demodulize(model_class.name)))
|
31
|
+
self.model_not_found = error_message || "#{Inflector.humanize(Inflector.underscore(Inflector.demodulize(model_class.name)))} not found".freeze
|
32
32
|
end
|
33
33
|
|
34
34
|
def inherited(subclass)
|
35
35
|
super
|
36
|
-
subclass.model_class
|
37
|
-
subclass.search_field
|
36
|
+
subclass.model_class = model_class
|
37
|
+
subclass.search_field = search_field
|
38
|
+
subclass.model_not_found = model_not_found
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
data/lib/pathway/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pathway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pablo Herrero
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-inflector
|