pathway 0.12.3 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83205585dcf796cdb4a5da8055163491d12586c48915e6d3ef7efe44ff6533f3
4
- data.tar.gz: 1584cfc7dd38e44e14a810a96a658e29b5756aad62f36e1e69671a3c7631a656
3
+ metadata.gz: dc09be062809a2afe5a1874e1da97c15be0353059116e2932d8224d0857b3899
4
+ data.tar.gz: dbc788f70ba9f95bfa700c790aff1a1c2313b2802b58417e4598314263c2af6a
5
5
  SHA512:
6
- metadata.gz: ade86174156600eb76a84af9ca96097eaa28a8760ba52f150fc9ed6c21ca5a69e387157cb7238c97990aa516ff712b98708941acf4885805e9bb4f8d85db2757
7
- data.tar.gz: 855252fa3e0639a3d18bd1f0f10f7d379795516723da702c6201076a3767dc3a7f447191260d137f57716bf57915e654270a0209b6b3e36de9896e54faac7927
6
+ metadata.gz: e39b0e7702a87427d242f722deb03ccf18186bb47e271a1fbb2c218bd1bde948db7fece51805a2b8de0c3f232273f624dd4c28cf743a50aa83bf00262c161cf2
7
+ data.tar.gz: 2b528a4f6c8f8172294265fafe0e3751c62a3412bc67a2deeef09f124dd38a419302502e7c7be77ead661088b3ccb54c2eb0f35c65e848a0e5947117470d294f
@@ -11,7 +11,7 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  strategy:
13
13
  matrix:
14
- ruby-version: [2.6, 2.7, 3.0, 3.1, 3.2, 3.3]
14
+ ruby-version: [3.1, 3.2, 3.3]
15
15
  steps:
16
16
  - uses: actions/checkout@v3
17
17
  - name: Set up Ruby
@@ -23,7 +23,7 @@ jobs:
23
23
  - name: Run tests
24
24
  run: bundle exec rake
25
25
  - name: Coveralls GitHub Action
26
- if: matrix.ruby-version == '3.2'
26
+ if: matrix.ruby-version == '3.3'
27
27
  uses: coverallsapp/github-action@v2
28
28
  with:
29
29
  github-token: ${{ secrets.GITHUB_TOKEN }}
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [1.0.0] - 2025-05-19
2
+ ### Changed
3
+ - Removed support for `Ruby` versions older than 3.0
4
+ - Removed support for `dry-validation` versions older than 1.0
5
+
1
6
  ## [0.12.3] - 2024-08-13
2
7
  ### Changed
3
8
  - Renamed config option `:auto_wire_options` to `:auto_wire` at `:dry_validation` plugin
data/README.md CHANGED
@@ -474,10 +474,6 @@ end
474
474
 
475
475
  The `with:` parameter can always be specified for `step :validate`, and allows you to override the default mapping regardless if auto-wiring is active or not.
476
476
 
477
- ##### Older versions of `dry-validation`
478
-
479
- Pathway supports the `dry-validation` gem down to version `0.11` (inclusive) in case you still have unmigrated code. When using versions below `1.0` the concept of contract is not present and instead of calling the `contract` method to set up 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.
480
-
481
477
  #### `SimpleAuth` plugin
482
478
 
483
479
  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.
@@ -1,12 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if RUBY_VERSION =~ /^3\./
4
- require 'pathway/plugins/auto_deconstruct_state/ruby3'
5
- end
6
-
7
3
  module Pathway
8
4
  module Plugins
9
5
  module AutoDeconstructState
6
+ module DSLMethods
7
+ private
8
+
9
+ def _callable(callable)
10
+ if callable.is_a?(Symbol) && @operation.respond_to?(callable, true) &&
11
+ @operation.method(callable).arity != 0 &&
12
+ @operation.method(callable).parameters.all? { _1 in [:key|:keyreq|:keyrest|:block,*] }
13
+
14
+ -> state { @operation.send(callable, **state) }
15
+ else
16
+ super
17
+ end
18
+ end
19
+ end
10
20
  end
11
21
  end
12
22
  end
@@ -5,21 +5,82 @@ require 'dry/validation'
5
5
  module Pathway
6
6
  module Plugins
7
7
  module DryValidation
8
- def self.apply(operation, **kwargs)
8
+ module ClassMethods
9
+ attr_reader :contract_class, :contract_options
10
+ attr_accessor :auto_wire
11
+
12
+ alias_method :auto_wire_options, :auto_wire
13
+ alias_method :auto_wire_options=, :auto_wire=
14
+
15
+ def contract(base = nil, &block)
16
+ if block_given?
17
+ base ||= _base_contract
18
+ self.contract_class = Class.new(base, &block)
19
+ elsif base
20
+ self.contract_class = base
21
+ else
22
+ raise ArgumentError, 'Either a contract class or a block must be provided'
23
+ end
24
+ end
25
+
26
+ def params(*args, **kwargs, &block)
27
+ contract { params(*args, **kwargs, &block) }
28
+ end
29
+
30
+ def contract_class= klass
31
+ @contract_class = klass
32
+ @contract_options = (klass.dry_initializer.options - Dry::Validation::Contract.dry_initializer.options).map(&:target)
33
+ @builded_contract = @contract_options.empty? && klass.schema ? klass.new : nil
34
+ end
35
+
36
+ def build_contract(**opts)
37
+ @builded_contract || contract_class.new(**opts)
38
+ end
39
+
40
+ def inherited(subclass)
41
+ super
42
+ subclass.auto_wire = auto_wire
43
+ subclass.contract_class = contract_class
44
+ end
45
+
46
+ private
47
+
48
+ def _base_contract
49
+ superclass.respond_to?(:contract_class) ? superclass.contract_class : Dry::Validation::Contract
50
+ end
51
+ end
52
+
53
+ module InstanceMethods
54
+ extend Forwardable
55
+
56
+ delegate %i[build_contract contract_options auto_wire_options auto_wire] => 'self.class'
57
+ alias_method :contract, :build_contract
58
+
59
+ def validate(state, with: nil)
60
+ if auto_wire && contract_options.any?
61
+ with ||= contract_options.zip(contract_options).to_h
62
+ end
63
+ opts = Hash(with).map { |to, from| [to, state[from]] }.to_h
64
+ validate_with(state[:input], **opts)
65
+ .then { |params| state.update(params:) }
66
+ end
67
+
68
+ def validate_with(input, **opts)
69
+ result = contract(**opts).call(input)
70
+
71
+ result.success? ? wrap(result.values.to_h) : error(:validation, details: result.errors.to_h)
72
+ end
73
+ end
74
+
75
+ def self.apply(operation, auto_wire_options: (auto_wire_options_was_not_used=true; false), auto_wire: auto_wire_options)
9
76
  #: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)
77
+ unless auto_wire_options_was_not_used
78
+ warn "[DEPRECATION] `auto_wire_options` is deprecated. Please use `auto_wire` instead"
21
79
  end
22
80
  #:nocov:
81
+
82
+ operation.auto_wire = auto_wire
83
+ operation.contract_class = Dry::Validation::Contract
23
84
  end
24
85
  end
25
86
  end
@@ -4,8 +4,8 @@ module Pathway
4
4
  module Plugins
5
5
  module Responder
6
6
  module ClassMethods
7
- ruby2_keywords def call(*args, &bl)
8
- result = super(*args)
7
+ def call(*args, **kwargs, &bl)
8
+ result = super(*args, **kwargs)
9
9
  block_given? ? Responder.respond(result, &bl) : result
10
10
  end
11
11
  end
@@ -21,9 +21,7 @@ module Pathway
21
21
  instance_eval(&bl)
22
22
  end
23
23
 
24
- def success(&bl)
25
- @ok = bl
26
- end
24
+ def success(&bl)= @ok = bl
27
25
 
28
26
  def failure(type = nil, &bl)
29
27
  if type.nil?
@@ -6,33 +6,33 @@ module Pathway
6
6
  module Plugins
7
7
  module SequelModels
8
8
  module DSLMethods
9
- def transaction(step_name = nil, &bl)
10
- fail 'must provide a step or a block but not both' if !step_name.nil? == block_given?
9
+ def transaction(step_name = nil, &dsl_bl)
10
+ raise 'must provide a step or a block but not both' if !step_name.nil? == block_given?
11
11
 
12
12
  if step_name
13
13
  transaction { step step_name }
14
14
  else
15
- around(-> steps, _ {
15
+ around(->(runner, _) {
16
16
  db.transaction(savepoint: true) do
17
- raise Sequel::Rollback if steps.call.failure?
17
+ raise Sequel::Rollback if runner.call.failure?
18
18
  end
19
- }, &bl)
19
+ }, &dsl_bl)
20
20
  end
21
21
  end
22
22
 
23
- def after_commit(step_name = nil, &bl)
24
- fail 'must provide a step or a block but not both' if !step_name.nil? == block_given?
23
+ def after_commit(step_name = nil, &dsl_bl)
24
+ raise 'must provide a step or a block but not both' if !step_name.nil? == block_given?
25
25
 
26
26
  if step_name
27
27
  after_commit { step step_name }
28
28
  else
29
- around(-> steps, state {
30
- dsl = self.class::DSL.new(State.new(self, state.to_h.dup), self)
29
+ around(->(runner, state) {
30
+ dsl_copy = self.class::DSL.new(State.new(self, state.to_h.dup), self)
31
31
 
32
32
  db.after_commit do
33
- steps.call(dsl)
33
+ runner.call(dsl_copy)
34
34
  end
35
- }, &bl)
35
+ }, &dsl_bl)
36
36
  end
37
37
  end
38
38
  end
@@ -41,10 +41,10 @@ module Pathway
41
41
  attr_accessor :model_class, :search_field, :model_not_found
42
42
 
43
43
  def model(model_class, search_by: model_class.primary_key, set_result_key: true, set_context_param: true, error_message: nil)
44
- self.model_class = model_class
45
- self.search_field = search_by
46
- self.result_key = Inflector.underscore(Inflector.demodulize(model_class.name)).to_sym if set_result_key
47
- self.model_not_found = error_message || "#{Inflector.humanize(Inflector.underscore(Inflector.demodulize(model_class.name)))} not found".freeze
44
+ self.model_class = model_class
45
+ self.search_field = search_by
46
+ self.result_key = Inflector.underscore(Inflector.demodulize(model_class.name)).to_sym if set_result_key
47
+ self.model_not_found = error_message || "#{Inflector.humanize(Inflector.underscore(Inflector.demodulize(model_class.name)))} not found".freeze
48
48
 
49
49
  self.context(result_key => Contextualizer::OPTIONAL) if set_result_key && set_context_param
50
50
  end
@@ -26,9 +26,7 @@ module Pathway
26
26
  authorized?(*objs) ? wrap(objs) : error(:forbidden)
27
27
  end
28
28
 
29
- def authorized?(*)
30
- true
31
- end
29
+ def authorized?(*) = true
32
30
  end
33
31
  end
34
32
  end
@@ -6,13 +6,8 @@ module Pathway
6
6
  attr_reader :value, :error
7
7
 
8
8
  class Success < Result
9
- def initialize(value)
10
- @value = value
11
- end
12
-
13
- def success?
14
- true
15
- end
9
+ def initialize(value) = @value = value
10
+ def success? = true
16
11
 
17
12
  def then(bl=nil)
18
13
  result(block_given? ? yield(value): bl.call(value))
@@ -25,29 +20,18 @@ module Pathway
25
20
 
26
21
  private
27
22
 
28
- alias :value_for_deconstruct :value
23
+ alias_method :value_for_deconstruct, :value
29
24
  end
30
25
 
31
26
  class Failure < Result
32
- def initialize(error)
33
- @error = error
34
- end
35
-
36
- def success?
37
- false
38
- end
39
-
40
- def then(_=nil)
41
- self
42
- end
43
-
44
- def tee(_=nil)
45
- self
46
- end
27
+ def initialize(error) = @error = error
28
+ def success? = false
29
+ def then(_=nil) = self
30
+ def tee(_=nil) = self
47
31
 
48
32
  private
49
33
 
50
- alias :value_for_deconstruct :error
34
+ alias_method :value_for_deconstruct, :error
51
35
  end
52
36
 
53
37
  module Mixin
@@ -55,10 +39,16 @@ module Pathway
55
39
  Failure = Result::Failure
56
40
  end
57
41
 
58
- def deconstruct
59
- [value_for_deconstruct]
42
+ def self.success(value) = Success.new(value)
43
+ def self.failure(error) = Failure.new(error)
44
+
45
+ def self.result(object)
46
+ object.is_a?(Result) ? object : success(object)
60
47
  end
61
48
 
49
+ def failure? = !success?
50
+ def deconstruct = [value_for_deconstruct]
51
+
62
52
  def deconstruct_keys(keys)
63
53
  if value_for_deconstruct.respond_to?(:deconstruct_keys)
64
54
  value_for_deconstruct.deconstruct_keys(keys)
@@ -67,22 +57,6 @@ module Pathway
67
57
  end
68
58
  end
69
59
 
70
- def failure?
71
- !success?
72
- end
73
-
74
- def self.success(value)
75
- Success.new(value)
76
- end
77
-
78
- def self.failure(error)
79
- Failure.new(error)
80
- end
81
-
82
- def self.result(object)
83
- object.is_a?(Result) ? object : success(object)
84
- end
85
-
86
60
  delegate :result => 'self.class'
87
61
  end
88
62
  end
@@ -22,22 +22,22 @@ RSpec::Matchers.define :fail_on do |input|
22
22
  @type = type
23
23
  end
24
24
 
25
- alias :with_type :type
26
- alias :and_type :type
25
+ alias_method :with_type, :type
26
+ alias_method :and_type, :type
27
27
 
28
28
  chain :message do |message|
29
29
  @message = message
30
30
  end
31
31
 
32
- alias :with_message :message
33
- alias :and_message :message
32
+ alias_method :with_message, :message
33
+ alias_method :and_message, :message
34
34
 
35
35
  chain :details do |details|
36
36
  @details = details
37
37
  end
38
38
 
39
- alias :with_details :details
40
- alias :and_details :details
39
+ alias_method :with_details, :details
40
+ alias_method :and_details, :details
41
41
 
42
42
  description do
43
43
  'fail' + (@type ? " with :#@type error" : '')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pathway
4
- VERSION = '0.12.3'
4
+ VERSION = '1.0.0'
5
5
  end
data/lib/pathway.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ruby2_keywords'
4
3
  require 'forwardable'
5
4
  require 'dry/inflector'
6
5
  require 'contextualizer'
@@ -11,7 +10,7 @@ module Pathway
11
10
  Inflector = Dry::Inflector.new
12
11
  class Operation
13
12
  class << self
14
- ruby2_keywords def plugin(name, *args)
13
+ def plugin(name,...)
15
14
  require "pathway/plugins/#{Inflector.underscore(name)}" if name.is_a?(Symbol)
16
15
 
17
16
  plugin = name.is_a?(Module) ? name : Plugins.const_get(Inflector.camelize(name))
@@ -20,7 +19,7 @@ module Pathway
20
19
  self.include plugin::InstanceMethods if plugin.const_defined? :InstanceMethods
21
20
  self::DSL.include plugin::DSLMethods if plugin.const_defined? :DSLMethods
22
21
 
23
- plugin.apply(self, *args) if plugin.respond_to?(:apply)
22
+ plugin.apply(self,...) if plugin.respond_to?(:apply)
24
23
  end
25
24
 
26
25
  def inherited(subclass)
@@ -45,13 +44,8 @@ module Pathway
45
44
  @details = details || {}
46
45
  end
47
46
 
48
- def deconstruct
49
- [type, message, details]
50
- end
51
-
52
- def deconstruct_keys(_)
53
- { type: type, message: message, details: details }
54
- end
47
+ def deconstruct = [type, message, details]
48
+ def deconstruct_keys(_) = { type:, message:, details: }
55
49
 
56
50
  private
57
51
 
@@ -62,35 +56,29 @@ module Pathway
62
56
 
63
57
  class State
64
58
  extend Forwardable
59
+ delegate %i([] []= fetch store include? values_at deconstruct_keys) => :@hash
65
60
 
66
61
  def initialize(operation, values = {})
67
62
  @hash = operation.context.merge(values)
68
63
  @result_key = operation.result_key
69
64
  end
70
65
 
71
- delegate %i([] []= fetch store include? values_at deconstruct_keys) => :@hash
72
-
73
66
  def update(kargs)
74
67
  @hash.update(kargs)
75
68
  self
76
69
  end
77
70
 
78
- def result
79
- @hash[@result_key]
80
- end
81
-
82
- def to_hash
83
- @hash
84
- end
71
+ def result = @hash[@result_key]
72
+ def to_hash = @hash
85
73
 
86
74
  def use(&bl)
87
75
  raise ArgumentError, 'a block must be provided' if !block_given?
88
- if bl.parameters.any? {|(type,_)| type == :keyrest || type == :rest }
76
+ if bl.parameters in [*, [:rest|:keyrest,], *]
89
77
  raise ArgumentError, 'rest arguments are not supported'
90
78
  end
91
79
 
92
- keys = bl.parameters.select {|(type,_)| type == :key || type == :keyreq }.map(&:last)
93
- names = bl.parameters.select {|(type,_)| type == :req || type == :opt }.map(&:last)
80
+ keys = bl.parameters.select { _1 in :key|:keyreq, }.map(&:last)
81
+ names = bl.parameters.select { _1 in :req|:opt, }.map(&:last)
94
82
 
95
83
  if keys.any? && names.any?
96
84
  raise ArgumentError, 'cannot mix positional and keyword arguments'
@@ -110,20 +98,19 @@ module Pathway
110
98
  module Base
111
99
  module ClassMethods
112
100
  attr_accessor :result_key
113
- alias :result_at :result_key=
101
+
102
+ alias_method :result_at, :result_key=
114
103
 
115
104
  def process(&bl)
116
105
  dsl = self::DSL
117
106
  define_method(:call) do |input|
118
- dsl.new(State.new(self, input: input), self)
107
+ dsl.new(State.new(self, input:), self)
119
108
  .run(&bl)
120
109
  .then(&:result)
121
110
  end
122
111
  end
123
112
 
124
- ruby2_keywords def call(ctx, *params)
125
- new(ctx).call(*params)
126
- end
113
+ def call(ctx,...) = new(ctx).call(...)
127
114
 
128
115
  def inherited(subclass)
129
116
  super
@@ -137,18 +124,16 @@ module Pathway
137
124
  delegate :result_key => 'self.class'
138
125
  delegate %i[result success failure] => Result
139
126
 
140
- alias :wrap :result
127
+ alias_method :wrap, :result
141
128
 
142
- def call(*)
143
- fail 'must implement at subclass'
144
- end
129
+ def call(*) = raise 'must implement at subclass'
145
130
 
146
131
  def error(type, message: nil, details: nil)
147
- failure(Error.new(type: type, message: message, details: details))
132
+ failure(Error.new(type:, message:, details:))
148
133
  end
149
134
 
150
135
  def wrap_if_present(value, type: :not_found, message: nil, details: {})
151
- value.nil? ? error(type, message: message, details: details) : success(value)
136
+ value.nil? ? error(type, message:, details:) : success(value)
152
137
  end
153
138
  end
154
139
 
@@ -168,45 +153,43 @@ module Pathway
168
153
  end
169
154
 
170
155
  # Execute step and preserve the former state
171
- ruby2_keywords def step(callable, *args)
156
+ def step(callable,...)
172
157
  bl = _callable(callable)
173
-
174
- @result = @result.tee { |state| bl.call(state, *args) }
158
+ @result = @result.tee { |state| bl.call(state,...) }
175
159
  end
176
160
 
177
161
  # Execute step and modify the former state setting the key
178
- def set(callable, *args, to: @operation.result_key)
162
+ def set(callable, *args, to: @operation.result_key, **kwargs, &bl)
179
163
  bl = _callable(callable)
180
164
 
181
165
  @result = @result.then do |state|
182
- wrap(bl.call(state, *args))
166
+ wrap(bl.call(state, *args, **kwargs, &bl))
183
167
  .then { |value| state.update(to => value) }
184
168
  end
185
169
  end
186
170
 
187
171
  # Execute step and replace the current state completely
188
- def map(callable)
172
+ def map(callable,...)
189
173
  bl = _callable(callable)
190
- @result = @result.then(bl)
174
+ @result = @result.then { |state| bl.call(state,...) }
191
175
  end
192
176
 
193
- def around(wrapper, &steps)
177
+ def around(execution_strategy, &dsl_block)
194
178
  @result.then do |state|
195
- seq = -> (dsl = self) { @result = dsl.run(&steps) }
196
- _callable(wrapper).call(seq, state)
179
+ dsl_runner = ->(dsl = self) { @result = dsl.run(&dsl_block) }
180
+
181
+ _callable(execution_strategy).call(dsl_runner, state)
197
182
  end
198
183
  end
199
184
 
200
- def if_true(cond, &steps)
185
+ def if_true(cond, &dsl_block)
201
186
  cond = _callable(cond)
202
- around(-> seq, state {
203
- seq.call if cond.call(state)
204
- }, &steps)
187
+ around(->(dsl_runner, state) { dsl_runner.call if cond.call(state) }, &dsl_block)
205
188
  end
206
189
 
207
- def if_false(cond, &steps)
190
+ def if_false(cond, &dsl_block)
208
191
  cond = _callable(cond)
209
- if_true(-> state { !cond.call(state) }, &steps)
192
+ if_true(->(state) { !cond.call(state) }, &dsl_block)
210
193
  end
211
194
 
212
195
  alias_method :sequence, :around
@@ -214,16 +197,14 @@ module Pathway
214
197
 
215
198
  private
216
199
 
217
- def wrap(obj)
218
- Result.result(obj)
219
- end
200
+ def wrap(obj) = Result.result(obj)
220
201
 
221
202
  def _callable(callable)
222
203
  case callable
223
204
  when Proc
224
- -> *args { @operation.instance_exec(*args, &callable) }.ruby2_keywords
205
+ ->(*args, **kwargs) { @operation.instance_exec(*args, **kwargs, &callable) }
225
206
  when Symbol
226
- -> *args { @operation.send(callable, *args) }.ruby2_keywords
207
+ ->(*args, **kwargs) { @operation.send(callable, *args, **kwargs) }
227
208
  else
228
209
  callable
229
210
  end
data/pathway.gemspec CHANGED
@@ -27,13 +27,12 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- spec.required_ruby_version = ">= 2.4.0"
30
+ spec.required_ruby_version = ">= 3.1.0"
31
31
 
32
32
  spec.add_dependency "dry-inflector", ">= 0.1.0"
33
- spec.add_dependency "contextualizer", "~> 0.0.4"
34
- spec.add_dependency "ruby2_keywords"
33
+ spec.add_dependency "contextualizer", "~> 0.1.0"
35
34
 
36
- spec.add_development_dependency "dry-validation", ">= 0.11"
35
+ spec.add_development_dependency "dry-validation", ">= 1.0"
37
36
  spec.add_development_dependency "bundler", ">= 2.4.10"
38
37
  spec.add_development_dependency "sequel", "~> 5.0"
39
38
  spec.add_development_dependency "rake", "~> 13.0"
@@ -41,6 +40,7 @@ Gem::Specification.new do |spec|
41
40
  spec.add_development_dependency "simplecov-lcov", '~> 0.8.0'
42
41
  spec.add_development_dependency "simplecov"
43
42
  spec.add_development_dependency "pry"
43
+ spec.add_development_dependency "byebug"
44
44
  spec.add_development_dependency "pry-byebug"
45
45
  spec.add_development_dependency "pry-doc"
46
46
  spec.add_development_dependency "pry-stack"
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pathway
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Herrero
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-08-13 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: dry-inflector
@@ -30,42 +29,28 @@ dependencies:
30
29
  requirements:
31
30
  - - "~>"
32
31
  - !ruby/object:Gem::Version
33
- version: 0.0.4
32
+ version: 0.1.0
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
37
  - - "~>"
39
38
  - !ruby/object:Gem::Version
40
- version: 0.0.4
41
- - !ruby/object:Gem::Dependency
42
- name: ruby2_keywords
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
39
+ version: 0.1.0
55
40
  - !ruby/object:Gem::Dependency
56
41
  name: dry-validation
57
42
  requirement: !ruby/object:Gem::Requirement
58
43
  requirements:
59
44
  - - ">="
60
45
  - !ruby/object:Gem::Version
61
- version: '0.11'
46
+ version: '1.0'
62
47
  type: :development
63
48
  prerelease: false
64
49
  version_requirements: !ruby/object:Gem::Requirement
65
50
  requirements:
66
51
  - - ">="
67
52
  - !ruby/object:Gem::Version
68
- version: '0.11'
53
+ version: '1.0'
69
54
  - !ruby/object:Gem::Dependency
70
55
  name: bundler
71
56
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +149,20 @@ dependencies:
164
149
  - - ">="
165
150
  - !ruby/object:Gem::Version
166
151
  version: '0'
152
+ - !ruby/object:Gem::Dependency
153
+ name: byebug
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ type: :development
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
167
166
  - !ruby/object:Gem::Dependency
168
167
  name: pry-byebug
169
168
  requirement: !ruby/object:Gem::Requirement
@@ -228,11 +227,7 @@ files:
228
227
  - bin/setup
229
228
  - lib/pathway.rb
230
229
  - lib/pathway/plugins/auto_deconstruct_state.rb
231
- - lib/pathway/plugins/auto_deconstruct_state/ruby3.rb
232
230
  - lib/pathway/plugins/dry_validation.rb
233
- - lib/pathway/plugins/dry_validation/v0_11.rb
234
- - lib/pathway/plugins/dry_validation/v0_12.rb
235
- - lib/pathway/plugins/dry_validation/v1_0.rb
236
231
  - lib/pathway/plugins/responder.rb
237
232
  - lib/pathway/plugins/sequel_models.rb
238
233
  - lib/pathway/plugins/simple_auth.rb
@@ -254,7 +249,6 @@ licenses:
254
249
  metadata:
255
250
  bug_tracker_uri: https://github.com/pabloh/pathway/issues
256
251
  source_code_uri: https://github.com/pabloh/pathway
257
- post_install_message:
258
252
  rdoc_options: []
259
253
  require_paths:
260
254
  - lib
@@ -262,15 +256,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
262
256
  requirements:
263
257
  - - ">="
264
258
  - !ruby/object:Gem::Version
265
- version: 2.4.0
259
+ version: 3.1.0
266
260
  required_rubygems_version: !ruby/object:Gem::Requirement
267
261
  requirements:
268
262
  - - ">="
269
263
  - !ruby/object:Gem::Version
270
264
  version: '0'
271
265
  requirements: []
272
- rubygems_version: 3.5.10
273
- signing_key:
266
+ rubygems_version: 3.6.9
274
267
  specification_version: 4
275
268
  summary: Define your business logic in simple steps.
276
269
  test_files: []
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pathway
4
- module Plugins
5
- module AutoDeconstructState
6
- module DSLMethods
7
- private
8
-
9
- def _callable(callable)
10
- if callable.is_a?(Symbol) && @operation.respond_to?(callable, true) &&
11
- @operation.method(callable).arity != 0 &&
12
- @operation.method(callable).parameters.all? { _1 in [:key|:keyreq|:keyrest|:block,*] }
13
-
14
- -> state { @operation.send(callable, **state) }
15
- else
16
- super
17
- end
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pathway
4
- module Plugins
5
- module DryValidation
6
- module V0_11
7
- module ClassMethods
8
- attr_reader :form_class, :form_options
9
- attr_accessor :auto_wire
10
-
11
- alias_method :auto_wire_options, :auto_wire
12
- alias_method :auto_wire_options=, :auto_wire=
13
-
14
- def form(base = nil, **opts, &block)
15
- if block_given?
16
- base ||= _base_form
17
- self.form_class = _block_definition(base, opts, &block)
18
- elsif base
19
- self.form_class = _form_class(base)
20
- else
21
- raise ArgumentError, 'Either a form class or a block must be provided'
22
- end
23
- end
24
-
25
- def form_class= klass
26
- @builded_form = klass.options.empty? ? klass.new : nil
27
- @form_class = klass
28
- @form_options = klass.options.keys
29
- end
30
-
31
- def build_form(opts = {})
32
- @builded_form || form_class.new(opts)
33
- end
34
-
35
- def inherited(subclass)
36
- super
37
- subclass.form_class = form_class
38
- subclass.auto_wire = auto_wire
39
- end
40
-
41
- private
42
-
43
- def _base_form
44
- superclass.respond_to?(:form_class) ? superclass.form_class : Dry::Validation::Schema::Form
45
- end
46
-
47
- def _form_class(form)
48
- form.is_a?(Class) ? form : form.class
49
- end
50
-
51
- def _form_opts(opts = {})
52
- opts.merge(build: false)
53
- end
54
-
55
- def _block_definition(base, opts, &block)
56
- Dry::Validation.Form(_form_class(base), _form_opts(opts), &block)
57
- end
58
- end
59
-
60
- module InstanceMethods
61
- extend Forwardable
62
-
63
- delegate %i[build_form form_options auto_wire_options] => 'self.class'
64
- delegate %i[build_form form_options auto_wire_options auto_wire] => 'self.class'
65
- alias_method :form, :build_form
66
-
67
- def validate(state, with: nil)
68
- if auto_wire && form_options.any?
69
- with ||= form_options.zip(form_options).to_h
70
- end
71
- opts = Hash(with).map { |opt, key| [opt, state[key]] }.to_h
72
- validate_with(state[:input], opts)
73
- .then { |params| state.update(params: params) }
74
- end
75
-
76
- def validate_with(params, opts = {})
77
- val = form(opts).call(params)
78
-
79
- val.success? ? wrap(val.output) : error(:validation, details: val.messages)
80
- end
81
- end
82
-
83
- def self.apply(operation, auto_wire_options: (auto_wire_options_was_not_used=true; false), auto_wire: auto_wire_options)
84
- #:nocov:
85
- unless auto_wire_options_was_not_used
86
- warn "[DEPRECATION] `auto_wire_options` is deprecated. Please use `auto_wire` instead"
87
- end
88
- #:nocov:
89
-
90
- operation.auto_wire = auto_wire
91
- operation.form_class = Dry::Validation::Schema::Form
92
- end
93
- end
94
- end
95
- end
96
- end
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pathway
4
- module Plugins
5
- module DryValidation
6
- module V0_12
7
- module ClassMethods
8
- attr_reader :form_class, :form_options
9
- attr_accessor :auto_wire
10
-
11
- alias_method :auto_wire_options, :auto_wire
12
- alias_method :auto_wire_options=, :auto_wire=
13
-
14
- def form(base = nil, **opts, &block)
15
- if block_given?
16
- base ||= _base_form
17
- self.form_class = _block_definition(base, opts, &block)
18
- elsif base
19
- self.form_class = _form_class(base)
20
- else
21
- raise ArgumentError, 'Either a form class or a block must be provided'
22
- end
23
- end
24
-
25
- def form_class= klass
26
- @builded_form = klass.options.empty? ? klass.new : nil
27
- @form_class = klass
28
- @form_options = klass.options.keys
29
- end
30
-
31
- def build_form(opts = {})
32
- @builded_form || form_class.new(opts)
33
- end
34
-
35
- def inherited(subclass)
36
- super
37
- subclass.form_class = form_class
38
- subclass.auto_wire = auto_wire
39
- end
40
-
41
- private
42
-
43
- def _base_form
44
- superclass.respond_to?(:form_class) ? superclass.form_class : Dry::Validation::Schema::Params
45
- end
46
-
47
- def _form_class(form)
48
- form.is_a?(Class) ? form : form.class
49
- end
50
-
51
- def _form_opts(opts = {})
52
- opts.merge(build: false)
53
- end
54
-
55
- def _block_definition(base, opts, &block)
56
- Dry::Validation.Params(_form_class(base), _form_opts(opts), &block)
57
- end
58
- end
59
-
60
- module InstanceMethods
61
- extend Forwardable
62
-
63
- delegate %i[build_form form_options auto_wire_options auto_wire] => 'self.class'
64
- alias_method :form, :build_form
65
-
66
- def validate(state, with: nil)
67
- if auto_wire && form_options.any?
68
- with ||= form_options.zip(form_options).to_h
69
- end
70
- opts = Hash(with).map { |opt, key| [opt, state[key]] }.to_h
71
- validate_with(state[:input], opts)
72
- .then { |params| state.update(params: params) }
73
- end
74
-
75
- def validate_with(params, opts = {})
76
- val = form(opts).call(params)
77
-
78
- val.success? ? wrap(val.output) : error(:validation, details: val.messages)
79
- end
80
- end
81
-
82
- def self.apply(operation, auto_wire_options: (auto_wire_options_was_not_used=true; false), auto_wire: auto_wire_options)
83
- #:nocov:
84
- unless auto_wire_options_was_not_used
85
- warn "[DEPRECATION] `auto_wire_options` is deprecated. Please use `auto_wire` instead"
86
- end
87
- #:nocov:
88
-
89
- operation.auto_wire = auto_wire
90
- operation.form_class = Dry::Validation::Schema::Params
91
- end
92
- end
93
- end
94
- end
95
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pathway
4
- module Plugins
5
- module DryValidation
6
- module V1_0
7
- module ClassMethods
8
- attr_reader :contract_class, :contract_options
9
- attr_accessor :auto_wire
10
-
11
- alias_method :auto_wire_options, :auto_wire
12
- alias_method :auto_wire_options=, :auto_wire=
13
-
14
- def contract(base = nil, &block)
15
- if block_given?
16
- base ||= _base_contract
17
- self.contract_class = Class.new(base, &block)
18
- elsif base
19
- self.contract_class = base
20
- else
21
- raise ArgumentError, 'Either a contract class or a block must be provided'
22
- end
23
- end
24
-
25
- ruby2_keywords def params(*args, &block)
26
- contract { params(*args, &block) }
27
- end
28
-
29
- def contract_class= klass
30
- @contract_class = klass
31
- @contract_options = (klass.dry_initializer.options - Dry::Validation::Contract.dry_initializer.options).map(&:target)
32
- @builded_contract = @contract_options.empty? && klass.schema ? klass.new : nil
33
- end
34
-
35
- def build_contract(**opts)
36
- @builded_contract || contract_class.new(**opts)
37
- end
38
-
39
- def inherited(subclass)
40
- super
41
- subclass.auto_wire = auto_wire
42
- subclass.contract_class = contract_class
43
- end
44
-
45
- private
46
-
47
- def _base_contract
48
- superclass.respond_to?(:contract_class) ? superclass.contract_class : Dry::Validation::Contract
49
- end
50
- end
51
-
52
- module InstanceMethods
53
- extend Forwardable
54
-
55
- delegate %i[build_contract contract_options auto_wire_options auto_wire] => 'self.class'
56
- alias_method :contract, :build_contract
57
-
58
- def validate(state, with: nil)
59
- if auto_wire && contract_options.any?
60
- with ||= contract_options.zip(contract_options).to_h
61
- end
62
- opts = Hash(with).map { |to, from| [to, state[from]] }.to_h
63
- validate_with(state[:input], **opts)
64
- .then { |params| state.update(params: params) }
65
- end
66
-
67
- def validate_with(input, **opts)
68
- result = contract(**opts).call(input)
69
-
70
- result.success? ? wrap(result.values.to_h) : error(:validation, details: result.errors.to_h)
71
- end
72
- end
73
-
74
- def self.apply(operation, auto_wire_options: (auto_wire_options_was_not_used=true; false), auto_wire: auto_wire_options)
75
- #:nocov:
76
- unless auto_wire_options_was_not_used
77
- warn "[DEPRECATION] `auto_wire_options` is deprecated. Please use `auto_wire` instead"
78
- end
79
- #:nocov:
80
-
81
- operation.auto_wire = auto_wire
82
- operation.contract_class = Dry::Validation::Contract
83
- end
84
- end
85
- end
86
- end
87
- end