pathway 0.9.1 → 0.11.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f95391a7c8c39954f8ffb8bbaa8c06294bd28c3553e595d4f91e3b44a109b3ee
4
- data.tar.gz: 22118f62ae34e871d6258a59111614e83643d6557bde5cb1fb5381edff2fcab5
3
+ metadata.gz: f136383bd165f1ff88c16e5cb70fb16342b84e5b4e8b76bd49bf0fd91707e2ab
4
+ data.tar.gz: b4b5cc55ea74d704c66976004e968f72d721c928af86bc8e5660ede8c8d61073
5
5
  SHA512:
6
- metadata.gz: 942055689e4836b0556f9b1d1b2aa010b5391c322a3948598047be7ee1b06c83e19bb026efd90f6388aed035a2c37784a26350fa991fe28cf53a7d7f91c4cf9f
7
- data.tar.gz: 971070c4f8eec9bede60e354926a7114107b68cd2ead43083c319f7de709b62dd5013294344e105e64965598865cc8d91185462e5a15c880eefee051ca9ffdd3
6
+ metadata.gz: b83238e83c8f2835f5fa817b6c7e9bc91d68dd9362b97a371d2d22e5ff9a7f8695c26ac4a03fda5b23afebc4d6474744db85ad713c0f49eb2fec95b5696f206e
7
+ data.tar.gz: b8fd39d4709179ecacd79c89741e6402610afad146117acc82eea7ba2f0376fefcfd5d990a848bd55c0acfdccd64b5313e2497893078818091d8c28b136dd8e2
@@ -0,0 +1,38 @@
1
+ version: 2.0
2
+ shared: &shared
3
+ steps:
4
+ - checkout
5
+ - run:
6
+ name: Bundle gems
7
+ command: |
8
+ echo '--no-rdoc --no-ri' > '.gemrc'
9
+ bundle install --jobs=4 --retry=3 --path vendor/bundle
10
+ - run:
11
+ name: Run tests
12
+ command: bundle exec rspec --format documentation --color --format progress spec
13
+
14
+ jobs:
15
+ "ruby-2.4":
16
+ <<: *shared
17
+ docker:
18
+ - image: circleci/ruby:2.4
19
+
20
+ "ruby-2.5":
21
+ <<: *shared
22
+ docker:
23
+ - image: circleci/ruby:2.5
24
+
25
+ "ruby-2.6":
26
+ <<: *shared
27
+ docker:
28
+ - image: circleci/ruby:2.6
29
+ environment:
30
+ REPORT_COVERAGE: 'true'
31
+
32
+ workflows:
33
+ version: 2
34
+ build:
35
+ jobs:
36
+ - "ruby-2.4"
37
+ - "ruby-2.5"
38
+ - "ruby-2.6"
@@ -1,3 +1,25 @@
1
+ ## [0.11.3] - 2020-07-22
2
+ ### Changed
3
+ - Use default error message on `:fetch_model` step, at `:sequel_models` plugin, if model type cannot be determined
4
+
5
+ ## [0.11.2] - 2020-07-22
6
+ ### Changed
7
+ - Improve `from:` option for `:fetch_model` step, at `:sequel_models` plugin, to also accept a Sequel Dataset
8
+
9
+ ## [0.11.1] - 2020-01-09
10
+ ### Changed
11
+ - Improve custom `rspec` matchers for testing field presence on schemas
12
+
13
+ ## [0.11.0] - 2020-01-02
14
+ ### Changed
15
+ - Add support for `dry-validation` 1.0 and above
16
+
17
+ ## [0.10.0] - 2019-10-06
18
+ ### Changed
19
+ - Restrict support for `dry-validation` from 0.11.0 up to (excluding) 1.0.0
20
+ - Changed behavior for `:transaction` step wrapper, on `:sequel_models` plugin, to allow to take a single step name instead of block.
21
+ - Changed behavior for `:after_commit` step wrapper, on `:sequel_models` plugin, to allow to take a single step name instead of block.
22
+
1
23
  ## [0.9.1] - 2019-02-18
2
24
  ### Changed
3
25
  - Various improvements on documentation and gemspec.
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
- ruby '2.5.1'
2
-
3
1
  source "https://rubygems.org"
4
2
 
5
3
  # Specify your gem's dependencies in pathway.gemspec
data/README.md CHANGED
@@ -91,36 +91,37 @@ end
91
91
  #### Error objects
92
92
 
93
93
  `Pathway::Error` is a helper class to represent the error description from an failed operation execution (and can be used also for pattern matching as we'll see later).
94
- It's use is completely optional, but provides you with a basic schema to communicate what when wrong. You can instantiate it by calling `new` on the class itself or using the helper method `error` provided in the operation class:
94
+ Its use is completely optional, but provides you with a basic schema to communicate what when wrong. You can instantiate it by calling `new` on the class itself or using the helper method `error` provided by the operation class:
95
95
 
96
96
  ```ruby
97
97
  class CreateNugget < Pathway::Operation
98
98
  def call(input)
99
- validation = Form.call(input)
99
+ validation = Validator.call(input)
100
100
 
101
101
  if validation.ok?
102
102
  success(Nugget.create(validation.values))
103
103
  else
104
- error(type: :validation, message: 'Invalid input', details: validation.errors)
104
+ error(:validation, message: 'Invalid input', details: validation.errors)
105
105
  end
106
106
  end
107
107
  end
108
108
  ```
109
109
 
110
- As you can see `error(...)` expects `type:`, `message:` and `details` keyword arguments; `type:` is the only mandatory, the other ones can be omitted and have default values. Also `type` should be a `Symbol`, `message:` a `String` and `details:` can be a `Hash` or any other structure you see fit.
110
+ As you can see `error(...)` expects the `type` as the first parameter (and only the mandatory) then `message:` and `details` keyword arguments; these 2 last ones can be omitted and have default values. The type parameter must be a `Symbol`, `message:` a `String` and `details:` can be a `Hash` or any other structure you see fit.
111
111
 
112
- You then have accessors available on the error object to get the values back:
112
+ Finally, the `Error` object have three accessors available to get the values back:
113
113
 
114
114
  ```ruby
115
115
  result = CreateNugget.new.call(foo: 'foobar')
116
116
  if result.failure?
117
117
  puts "#{result.error.type} error: #{result.error.message}"
118
+ puts "Error details: #{result.error.details}"
118
119
  end
119
120
 
120
121
  ```
121
122
 
122
123
  Mind you, `error(...)` creates an `Error` object wrapped into a `Pathway::Failure` so you don't have to do it yourself.
123
- If you decide to use `Pathway::Error.new(...)` directly, the expected arguments will be the same, but you will have to wrap the object before returning it.
124
+ If you decide to use `Pathway::Error.new(...)` directly, you will have to pass all the arguments as keywords (including `type:`), and you will have to wrap the object before returning it.
124
125
 
125
126
  #### Initialization context
126
127
 
@@ -135,7 +136,7 @@ class CreateNugget < Pathway::Operation
135
136
  context :current_user, notify: false
136
137
 
137
138
  def call(input)
138
- validation = Form.call(input)
139
+ validation = Validator.call(input)
139
140
 
140
141
  if validation.valid?
141
142
  nugget = Nugget.create(owner: current_user, **validation.values)
@@ -143,7 +144,7 @@ class CreateNugget < Pathway::Operation
143
144
  Notifier.notify(:new_nugget, nugget) if @notify
144
145
  success(nugget)
145
146
  else
146
- error(type: :validation, message: 'Invalid input', details: validation.errors)
147
+ error(:validation, message: 'Invalid input', details: validation.errors)
147
148
  end
148
149
  end
149
150
  end
@@ -266,7 +267,7 @@ class CreateNugget < Pathway::Operation
266
267
  if validation.ok?
267
268
  state[:params] = validation.values
268
269
  else
269
- error(type: :validation, details: validation.errors)
270
+ error(:validation, details: validation.errors)
270
271
  end
271
272
  end
272
273
 
@@ -313,8 +314,8 @@ class SomeOperation < BaseOperation
313
314
  end
314
315
  ```
315
316
 
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.
317
- When activated it will enrich your operations with new instance and class methods plus extra customs step for the process DSL.
317
+ The plugin name must be specified as a `Symbol` (or also as the `Module` where is implemented, but more on that later), and it can take parameters next to the plugin's name.
318
+ When activated it will enrich your operations with new instance and class methods plus extra customs step for the `process` DSL.
318
319
 
319
320
  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.
320
321
 
@@ -322,21 +323,23 @@ Mind you, if you wish to activate a plugin for a number of operations you can ac
322
323
 
323
324
  This plugin provides integration with the [dry-validation](http://dry-rb.org/gems/dry-validation/) gem. I won't explain in detail how to use this library since is already extensively documented on its official website, but instead I'll assume certain knowledge of it, nonetheless, as you'll see in a moment, its API pretty self-explanatory.
324
325
 
325
- `dry-validation` provides a very simple way to define form (or schema) objects to process and validate our input. The provided custom `:validate` step allows you to run your input though a form to check your data is valid before continuing. When the input is invalid it will return an error object with type `:validation` and the reasons the validation failed on the `details` attribute. Is commonly the first step any operation runs.
326
+ `dry-validation` provides a very simple way to define contract objects (conceptually very similar to form objects) to process and validate input. The provided custom `:validate` step allows you to run your input though a contract to check if your data is valid before carrying on. When the input is invalid it will return an error object of type `:validation` and the reasons the validation failed will be available at the `details` attribute. Is usually the first step an operation runs.
326
327
 
327
- When using this plugin we'll have to provide an already defined form to the step to use or we can also define one inline.
328
+ When using this plugin we can provide an already defined contract to the step to use or we can also define it within the operation.
328
329
  Let's see a few examples:
329
330
 
330
331
  ```ruby
331
- NuggetForm = Dry::Validation.Form do
332
- required(:owner).filled(:str?)
333
- required(:price).filled(:int?)
332
+ class NuggetContract < Dry::Validation::Contract
333
+ params do
334
+ required(:owner).filled(:string)
335
+ required(:price).filled(:integer)
336
+ end
334
337
  end
335
338
 
336
339
  class CreateNugget < Pathway::Operation
337
340
  plugin :dry_validation
338
341
 
339
- form NuggetForm
342
+ contract NuggetContract
340
343
 
341
344
  process do
342
345
  step :validate
@@ -347,15 +350,17 @@ class CreateNugget < Pathway::Operation
347
350
  end
348
351
  ```
349
352
 
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`.
353
+ As is is shown above, the contract is defined first, then is configured it will be used by the operation by calling `contract NuggetContract`, and validate the input at the process block by placing the step `step :validate` inside the `process` block.
351
354
 
352
355
  ```ruby
353
356
  class CreateNugget < Pathway::Operation
354
357
  plugin :dry_validation
355
358
 
356
- form do
357
- required(:owner).filled(:str?)
358
- required(:price).filled(:int?)
359
+ contract do
360
+ params do
361
+ required(:owner).filled(:string)
362
+ required(:price).filled(:integer)
363
+ end
359
364
  end
360
365
 
361
366
  process do
@@ -367,16 +372,36 @@ class CreateNugget < Pathway::Operation
367
372
  end
368
373
  ```
369
374
 
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.
375
+ Now, this second example is equivalent to the first one, but here we call `contract` with a block instead and no parameter; this block will be used as definition body for a contract class that will be stored internally. Thus keeping the contract and operation code at the same place, this is convenient when you have a rather simpler contract and don't need to reuse it.
376
+
377
+ One interesting nuance to keep in mind regarding the inline block contract is that, when doing operation inheritance, if the parent operation already has a contract, the child operation will define a new one inheriting from the parent's. This is very useful to share validation logic among related operations in the same class hierarchy.
378
+
379
+ As a side note, if your contract is simple enough and only have params, you can call the `params` method directly instead, the following code is essentially equivalent to previous example:
380
+
381
+ ```ruby
382
+ class CreateNugget < Pathway::Operation
383
+ plugin :dry_validation
384
+
385
+ params do
386
+ required(:owner).filled(:string)
387
+ required(:price).filled(:integer)
388
+ end
389
+
390
+ process do
391
+ step :validate
392
+ step :create_nugget
393
+ end
371
394
 
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.
395
+ # ...
396
+ end
397
+ ```
373
398
 
374
- ##### Form options
399
+ ##### Contract options
375
400
 
376
- If you are familiar with `dry-validation` you probably know it provides a way to [inject options](http://dry-rb.org/gems/dry-validation/basics/working-with-schemas/#injecting-external-dependencies) before calling the form instance.
401
+ If you are familiar with `dry-validation` you probably know it provides a way to [inject options](https://dry-rb.org/gems/dry-validation/1.4/external-dependencies/) before calling the contract.
377
402
 
378
- On those scenarios you must either use the `auto_wire_options: true` plugin argument, or specify how to map options from the execution state to the form when calling `step :validate`.
379
- Lets see and example for each case:
403
+ On those scenarios you must either use the `auto_wire_options: true` plugin argument, or specify how to map options from the execution state to the contract when calling `step :validate`.
404
+ Lets see and example for the first case:
380
405
 
381
406
  ```ruby
382
407
  class CreateNugget < Pathway::Operation
@@ -384,11 +409,17 @@ class CreateNugget < Pathway::Operation
384
409
 
385
410
  context :user_name
386
411
 
387
- form do
388
- configure { option :user_name }
412
+ contract do
413
+ option :user_name
389
414
 
390
- required(:owner).filled(:str?, :eql?: user_name)
391
- required(:price).filled(:int?)
415
+ params do
416
+ required(:owner).filled(:string)
417
+ required(:price).filled(:integer)
418
+ end
419
+
420
+ rule(:owner) do
421
+ key.failure("invalid owner") unless user_name == values[:owner]
422
+ end
392
423
  end
393
424
 
394
425
  process do
@@ -400,25 +431,33 @@ class CreateNugget < Pathway::Operation
400
431
  end
401
432
  ```
402
433
 
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.
434
+ Here the defined contract 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 contract will already have the user name available.
404
435
 
405
436
  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 enabled for all your operations.
406
437
 
438
+ On the other hand, if for some reason the name of the contract's option and state attribute don't match, we can just pass `with: {...}` when calling to `step :validate`, indicating how to wire the attributes, the following example illustrates just that:
439
+
407
440
  ```ruby
408
441
  class CreateNugget < Pathway::Operation
409
442
  plugin :dry_validation
410
443
 
411
444
  context :current_user_name
412
445
 
413
- form do
414
- configure { option :user_name }
446
+ contract do
447
+ option :user_name
448
+
449
+ params do
450
+ required(:owner).filled(:string)
451
+ required(:price).filled(:integer)
452
+ end
415
453
 
416
- required(:owner).filled(:str?, :eql?: user_name)
417
- required(:price).filled(:int?)
454
+ rule(:owner) do
455
+ key.failure("invalid owner") unless user_name == values[:owner]
456
+ end
418
457
  end
419
458
 
420
459
  process do
421
- step :validate, with: { user_name: :current_user_name } # Inject :user_name to the form object with the state's :current_user_name
460
+ step :validate, with: { user_name: :current_user_name } # Inject :user_name to the contract object with the state's :current_user_name
422
461
  step :create_nugget
423
462
  end
424
463
 
@@ -426,10 +465,12 @@ class CreateNugget < Pathway::Operation
426
465
  end
427
466
  ```
428
467
 
429
- On the other hand, if for some reason the name of the form's option and state attribute don't match, we can just pass `with: {...}` when calling to `step :validate`, indicating how to wire the attributes, the example above illustrates just that.
430
-
431
468
  The `with:` parameter can always be specified, at `step :validate`, and allows you to override the default mapping regardless if auto-wiring is active or not.
432
469
 
470
+ ##### Older versions of `dry-validation`
471
+
472
+ Pathway supports the `dry-validation` gem down to version `0.11` (inclusive) in case you still have unmigrated code. When using versions bellow `1.0` the concept of contract is not present and instead of calling the `contract` method to setup your validation logic you must use the `form` method. Everything else remains the same except, obviously, that you would have to use `dry-definition`'s [old API](https://dry-rb.org/gems/dry-validation/0.13/) which is a bit different from the current one.
473
+
433
474
  #### `SimpleAuth` plugin
434
475
 
435
476
  This very simple plugin adds a custom step called `:authorize`, that can be used to check for permissions and halt the operation with a `:forbidden` error when they aren't fulfilled.
@@ -673,7 +714,7 @@ require 'pathway/rspec'
673
714
 
674
715
  #### Rspec matchers
675
716
 
676
- Pathway provide a few matchers in order to tests your operation easier.
717
+ Pathway provides a few matchers in order to tests your operation easier.
677
718
  Let's go through a full example and break it up in the following subsections:
678
719
 
679
720
  ```ruby
@@ -682,10 +723,10 @@ Let's go through a full example and break it up in the following subsections:
682
723
  class CreateNugget < Pathway::Operation
683
724
  plugin :dry_validation
684
725
 
685
- form do
686
- required(:owner).filled(:str?)
687
- required(:price).filled(:int?)
688
- optional(:disabled).maybe(:bool?)
726
+ params do
727
+ required(:owner).filled(:string)
728
+ required(:price).filled(:integer)
729
+ optional(:disabled).maybe(:bool)
689
730
  end
690
731
 
691
732
  process do
@@ -721,8 +762,8 @@ describe CreateNugget do
721
762
  end
722
763
  end
723
764
 
724
- describe '.form' do
725
- subject(:form) { CreateNugget.form }
765
+ describe '.contract' do
766
+ subject(:contract) { CreateNugget.build_contract }
726
767
 
727
768
  it { is_expected.to require_fields(:owner, :price) }
728
769
  it { is_expected.to accept_optional_field(:disabled) }
@@ -739,13 +780,13 @@ The assertion it performs is simply is that the operation was successful, also y
739
780
 
740
781
  This second matcher is analog to `succeed_on` but it asserts that operation execution was a failure instead. Also if you return an error object, and you need to, you can assert the error type using the `type` chain method (aliased as `and_type` and `with_type`); the error message (`and_message`, `with_message` or `message`); and the error details (`and_details`, `with_details` or `details`). Mind you, the chain methods for the message and details accept nested matchers while the `type` chain can only test by equality.
741
782
 
742
- ##### form matchers
783
+ ##### contract/form matchers
743
784
 
744
- Finally we can see that we are also testing the operation's form, implemented here with the `dry-validation` gem.
785
+ Finally we can see that we are also testing the operation's contract (or form), implemented here with the `dry-validation` gem.
745
786
 
746
- Two more matchers are provided when we use this gem: `require_fields` (aliased `require_field`) to test when form is expected to define a required set of fields, and `accept_optional_fields` (aliased `accept_optional_field`) to test when a form must define certain set of optional fields.
787
+ Two more matchers are provided: `require_fields` (aliased `require_field`) to test when a contract is expected to define a required set of fields, and `accept_optional_fields` (aliased `accept_optional_field`) to test when a contract must define a certain set of optional fields, both the contract class (at operation class method `contract_class`) or an instance (operation class method `build_contract`) can be provided.
747
788
 
748
- These matchers are only useful when using `dry-validation` and will very likely be extracted to its own gem in the future.
789
+ These matchers are only useful when using `dry-validation` (on every version newer or equal to `0.11.0`) and will probably be extracted to their own gem in the future.
749
790
 
750
791
  ## Development
751
792
 
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'forwardable'
2
4
  require 'dry/inflector'
3
5
  require 'contextualizer'
@@ -107,7 +109,7 @@ module Pathway
107
109
  alias :wrap :result
108
110
 
109
111
  def call(*)
110
- fail "must implement at subclass"
112
+ fail 'must implement at subclass'
111
113
  end
112
114
 
113
115
  def error(type, message: nil, details: nil)
@@ -1,99 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dry/validation'
2
4
 
3
5
  module Pathway
4
6
  module Plugins
5
7
  module DryValidation
6
- module ClassMethods
7
- attr_reader :form_class, :form_options
8
- attr_accessor :auto_wire_options
9
-
10
- def form(base = nil, **opts, &block)
11
- if block_given?
12
- base ||= _base_form
13
- self.form_class = _block_definition(base, opts, &block)
14
- elsif base
15
- self.form_class = _form_class(base)
16
- else
17
- raise ArgumentError, 'Either a form class or a block must be provided'
18
- end
19
- end
20
-
21
- def form_class= klass
22
- @builded_form = klass.options.empty? ? klass.new : nil
23
- @form_class = klass
24
- @form_options = klass.options.keys
25
- end
26
-
27
- def build_form(opts = {})
28
- @builded_form || form_class.new(opts)
29
- end
30
-
31
- def inherited(subclass)
32
- super
33
- subclass.form_class = form_class
34
- subclass.auto_wire_options = auto_wire_options
35
- end
36
-
37
- private
38
-
39
- def _base_form
40
- superclass.respond_to?(:form_class) ? superclass.form_class : DefaultFormClass
41
- end
42
-
43
- def _form_class(form)
44
- form.is_a?(Class) ? form : form.class
45
- end
46
-
47
- def _form_opts(opts = {})
48
- opts.merge(build: false)
49
- end
50
- end
51
-
52
- module InstanceMethods
53
- extend Forwardable
54
-
55
- delegate %i[build_form form_options auto_wire_options] => 'self.class'
56
- alias :form :build_form
57
-
58
- def validate(state, with: nil)
59
- if auto_wire_options && form_options.any?
60
- with ||= form_options.zip(form_options).to_h
61
- end
62
- opts = Hash(with).map { |opt, key| [opt, state[key]] }.to_h
63
- validate_with(state[:input], opts)
64
- .then { |params| state.update(params: params) }
65
- end
66
-
67
- def validate_with(params, opts = {})
68
- val = form(opts).call(params)
69
-
70
- val.success? ? wrap(val.output) : error(:validation, details: val.messages)
71
- end
72
- end
73
-
74
- def self.apply(operation, auto_wire_options: false)
75
- operation.form_class = DefaultFormClass
76
- operation.auto_wire_options = auto_wire_options
77
- end
78
-
79
- if Gem.loaded_specs['dry-validation'].version >= Gem::Version.new('0.12')
80
- DefaultFormClass = Dry::Validation::Schema::Params
81
-
82
- module ClassMethods
83
- private
84
- def _block_definition(base, opts, &block)
85
- Dry::Validation.Params(_form_class(base), _form_opts(opts), &block)
86
- end
87
- end
88
- else
89
- DefaultFormClass = Dry::Validation::Schema::Form
90
-
91
- module ClassMethods
92
- private
93
- def _block_definition(base, opts, &block)
94
- Dry::Validation.Form(_form_class(base), _form_opts(opts), &block)
95
- end
96
- end
8
+ def self.apply(operation, **kwargs)
9
+ #:nocov:
10
+ if Gem.loaded_specs['dry-validation'].version < Gem::Version.new('0.11')
11
+ fail 'unsupported dry-validation gem version'
12
+ elsif Gem.loaded_specs['dry-validation'].version < Gem::Version.new('0.12')
13
+ require 'pathway/plugins/dry_validation/v0_11'
14
+ operation.plugin(Plugins::DryValidation::V0_11, **kwargs)
15
+ elsif Gem.loaded_specs['dry-validation'].version < Gem::Version.new('1.0')
16
+ require 'pathway/plugins/dry_validation/v0_12'
17
+ operation.plugin(Plugins::DryValidation::V0_12, **kwargs)
18
+ else
19
+ require 'pathway/plugins/dry_validation/v1_0'
20
+ operation.plugin(Plugins::DryValidation::V1_0, **kwargs)
21
+ end
22
+ #:nocov:
97
23
  end
98
24
  end
99
25
  end