pathway 1.2.0 → 1.3.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: a13868cae6ff80203b023cdb1444609565f0004f0a2cab229997c01cbaa3aaa5
4
- data.tar.gz: c22500510ef22c61cf9e11beba23455287b38539f35c21a3e9c082f498e7ba0b
3
+ metadata.gz: d647d15611dc847cac56d22ff0b7dd34236ee8d67b62ffd84b7a252925f4c84a
4
+ data.tar.gz: 94ef8ed2ebd848e222e180b91e2c8969768cde5fcb1a65644c41f9adb4ee45ab
5
5
  SHA512:
6
- metadata.gz: 00012d3079c7487ca627bebcb24b5164dd08012082f40d7765bb0bb23a2e0210a9583ea18fa71fdd5f2c69be93d171459fe9ad5f159250bc46c67425fe7b4dd3
7
- data.tar.gz: 2c9557ffc6243159ff110a2e91d6017646020e05f990a1b3158ee46ccb1b2948993c085b06051a5eb9ea1eaa36ef3fb86b4858725fbb4966a9a2797bf0abf58e
6
+ metadata.gz: 60fac55bfa9c5105883209c9f44ea151a21e0720efd8e237bd66a06c46addf5c40c5c54ee24a69197aa9fd742c7a68edc4594c97365392f1e55711673ed4a80e
7
+ data.tar.gz: 03bb1724a76ea42a3bc079c7a349c740f55e82c13c4510308326465429c855cc6f949cb5ede7235fdb1f7c0e5f4a5e842c81ebf794423a011a07a07553763edf
@@ -11,19 +11,42 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  strategy:
13
13
  matrix:
14
- ruby-version: [3.2, 3.3, 3.4]
14
+ ruby-version: [3.3, 3.4, 4.0]
15
15
  steps:
16
16
  - uses: actions/checkout@v3
17
17
  - name: Set up Ruby
18
18
  uses: ruby/setup-ruby@v1
19
19
  with:
20
20
  ruby-version: ${{ matrix.ruby-version }}
21
- bundler: '2.4.22'
21
+ bundler: '2.5.6'
22
22
  bundler-cache: true
23
23
  - name: Run tests
24
24
  run: bundle exec rake
25
+ coveralls:
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - name: Set up Ruby
30
+ uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: '4.0'
33
+ bundler: '2.5.6'
34
+ bundler-cache: true
35
+ - name: Run tests for coverage
36
+ run: bundle exec rake
25
37
  - name: Coveralls GitHub Action
26
- if: matrix.ruby-version == '3.4'
27
38
  uses: coverallsapp/github-action@v2
28
39
  with:
29
40
  github-token: ${{ secrets.GITHUB_TOKEN }}
41
+ rubocop:
42
+ runs-on: ubuntu-latest
43
+ steps:
44
+ - uses: actions/checkout@v3
45
+ - name: Set up Ruby
46
+ uses: ruby/setup-ruby@v1
47
+ with:
48
+ ruby-version: '4.0'
49
+ bundler: '2.5.6'
50
+ bundler-cache: true
51
+ - name: Run RuboCop
52
+ run: bundle exec rubocop --force-exclusion
data/.rubocop.yml ADDED
@@ -0,0 +1,137 @@
1
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
2
+ # configuration file. It makes it possible to enable/disable
3
+ # certain cops (checks) and to alter their behavior if they accept
4
+ # any parameters. The file can be placed either in your home
5
+ # directory or in some project directory.
6
+ #
7
+ # RuboCop will start looking for the configuration file in the directory
8
+ # where the inspected file is and continue its way up to the root directory.
9
+ #
10
+ # See https://docs.rubocop.org/rubocop/configuration
11
+
12
+ plugins:
13
+ - rubocop-performance
14
+ - rubocop-rake
15
+
16
+ AllCops:
17
+ NewCops: enable
18
+ SuggestExtensions: false
19
+ Exclude:
20
+ - 'bin/*'
21
+ - 'vendor/**/*'
22
+
23
+ Style/Alias:
24
+ EnforcedStyle: prefer_alias_method
25
+
26
+ Style/StringLiterals:
27
+ EnforcedStyle: double_quotes
28
+
29
+ Style/HashSyntax:
30
+ Exclude:
31
+ - Rakefile
32
+
33
+ Metrics/BlockLength:
34
+ Exclude:
35
+ - 'spec/**/*.rb'
36
+ - 'lib/pathway/rspec/matchers/*.rb'
37
+ - 'pathway.gemspec'
38
+
39
+ Layout/EmptyLinesAroundBlockBody:
40
+ Exclude:
41
+ - 'spec/**/*.rb'
42
+
43
+ Layout/MultilineMethodCallIndentation:
44
+ EnforcedStyle: indented_relative_to_receiver
45
+
46
+ Naming/MethodParameterName:
47
+ MinNameLength: 2
48
+
49
+ Lint/MissingSuper:
50
+ AllowedParentClasses: [Result]
51
+
52
+ Style/AccessModifierDeclarations:
53
+ AllowModifiersOnAliasMethod: true
54
+
55
+ Gemspec/DevelopmentDependencies:
56
+ Enabled: true
57
+ EnforcedStyle: gemspec
58
+
59
+ Layout/HashAlignment:
60
+ EnforcedHashRocketStyle: table
61
+
62
+ Metrics/CyclomaticComplexity:
63
+ Max: 8
64
+
65
+ Metrics/AbcSize:
66
+ Max: 23
67
+
68
+ Metrics/MethodLength:
69
+ Max: 15
70
+
71
+ Metrics/PerceivedComplexity:
72
+ Max: 10
73
+
74
+ # Permanently Disabled
75
+ Style/GuardClause:
76
+ Enabled: false
77
+
78
+ Style/LambdaCall:
79
+ Enabled: false
80
+
81
+ Style/StringConcatenation:
82
+ Enabled: false
83
+
84
+ Style/Lambda:
85
+ Enabled: false
86
+
87
+ Style/Documentation:
88
+ Enabled: false
89
+
90
+ Layout/EmptyLinesAroundAccessModifier:
91
+ Enabled: false
92
+
93
+ Gemspec/OrderedDependencies:
94
+ Enabled: false
95
+
96
+ Style/ParallelAssignment:
97
+ Enabled: False
98
+
99
+ Style/TrailingCommaInHashLiteral:
100
+ Enabled: False
101
+
102
+ Style/RedundantSelf:
103
+ Enabled: False
104
+
105
+ Style/IfUnlessModifier:
106
+ Enabled: False
107
+
108
+ Lint/EmptyClass:
109
+ Enabled: False
110
+
111
+ # TODO: Temporally Disabled
112
+ Style/SafeNavigation:
113
+ Enabled: False
114
+
115
+ Layout/LeadingCommentSpace:
116
+ Enabled: False
117
+
118
+ Style/NumericLiterals:
119
+ Enabled: False
120
+
121
+ Style/CaseEquality:
122
+ Enabled: False
123
+
124
+ Performance/RedundantBlockCall:
125
+ Enabled: False
126
+
127
+ Lint/ConstantDefinitionInBlock:
128
+ Enabled: false
129
+
130
+ Layout/LineLength:
131
+ Enabled: false
132
+
133
+ Layout/SpaceInsideHashLiteralBraces:
134
+ Enabled: false
135
+
136
+ Metrics/ModuleLength:
137
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,7 +1,15 @@
1
+ ## [1.3.0] - 2026-03-25
2
+ ### Changed
3
+ - Removed support for `Ruby` versions older than 3.3
4
+ ### Removed
5
+ - Remove support for passing a block to the step method through `DSLMethods#step`
6
+ - Remove support for passing a block to the step method through `DSLMethods#set`
7
+ - Remove support for `DSLMethods#map`
8
+
1
9
  ## [1.2.0] - 2025-11-16
2
10
  ### Deprecated
3
- - Deprecate passing a block to the step method using `DSLMethods#step`
4
- - Deprecate passing a block to the step method using `DSLMethods#set`
11
+ - Deprecate passing a block to the step method through `DSLMethods#step`
12
+ - Deprecate passing a block to the step method through `DSLMethods#set`
5
13
  - Deprecate `DSLMethods#map`
6
14
  ### Changed
7
15
  - Removed deprecated `:auto_wire_options` option from `:dry_validation` plugin
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
5
  # Specify your gem's dependencies in pathway.gemspec
data/Rakefile CHANGED
@@ -3,10 +3,6 @@
3
3
  require "bundler/gem_tasks"
4
4
  require "rspec/core/rake_task"
5
5
 
6
- RSpec::Core::RakeTask.new(:spec) do |t|
7
- unless RUBY_VERSION =~ /^2\.7|^3\./
8
- t.exclude_pattern = 'spec/operation_call_pattern_matching_spec.rb,spec/state_pattern_matching_spec.rb'
9
- end
10
- end
6
+ RSpec::Core::RakeTask.new(:spec)
11
7
 
12
8
  task :default => :spec
data/bin/racc ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'racc' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("racc", "racc")
data/bin/rubocop ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("rubocop", "rubocop")
data/bin/ruby-parse ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'ruby-parse' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("parser", "ruby-parse")
data/bin/ruby-rewrite ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'ruby-rewrite' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("parser", "ruby-rewrite")
@@ -8,10 +8,10 @@ module Pathway
8
8
 
9
9
  def _callable(callable)
10
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,*] }
11
+ @operation.method(callable).arity != 0 &&
12
+ @operation.method(callable).parameters.all? { _1 in [:key | :keyreq | :keyrest | :block, *] }
13
13
 
14
- -> state { @operation.send(callable, **state) }
14
+ ->(state) { @operation.send(callable, **state) }
15
15
  else
16
16
  super
17
17
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/validation'
3
+ require "dry/validation"
4
4
 
5
5
  module Pathway
6
6
  module Plugins
@@ -16,7 +16,7 @@ module Pathway
16
16
  elsif base
17
17
  self.contract_class = base
18
18
  else
19
- raise ArgumentError, 'Either a contract class or a block must be provided'
19
+ raise ArgumentError, "Either a contract class or a block must be provided"
20
20
  end
21
21
  end
22
22
 
@@ -24,7 +24,7 @@ module Pathway
24
24
  contract { params(...) }
25
25
  end
26
26
 
27
- def contract_class= klass
27
+ def contract_class=(klass)
28
28
  @contract_class = klass
29
29
  @contract_options = (klass.dry_initializer.options - Dry::Validation::Contract.dry_initializer.options).map(&:target)
30
30
  @builded_contract = @contract_options.empty? && klass.schema ? klass.new : nil
@@ -50,14 +50,14 @@ module Pathway
50
50
  module InstanceMethods
51
51
  extend Forwardable
52
52
 
53
- delegate %i[build_contract contract_options auto_wire] => 'self.class'
53
+ delegate %i[build_contract contract_options auto_wire] => "self.class"
54
54
  alias_method :contract, :build_contract
55
55
 
56
56
  def validate(state, with: nil)
57
57
  if auto_wire && contract_options.any?
58
58
  with ||= contract_options.zip(contract_options).to_h
59
59
  end
60
- opts = Hash(with).map { |to, from| [to, state[from]] }.to_h
60
+ opts = Hash(with).transform_values { |from| state[from] }
61
61
  validate_with(state[:input], **opts)
62
62
  .then { |params| state.update(params:) }
63
63
  end
@@ -4,9 +4,9 @@ module Pathway
4
4
  module Plugins
5
5
  module Responder
6
6
  module ClassMethods
7
- def call(*args, **kwargs, &bl)
8
- result = super(*args, **kwargs)
9
- block_given? ? Responder.respond(result, &bl) : result
7
+ def call(*, **, &)
8
+ result = super(*, **)
9
+ block_given? ? Responder.respond(result, &) : result
10
10
  end
11
11
  end
12
12
 
@@ -34,7 +34,7 @@ module Pathway
34
34
  def respond
35
35
  if @result.success?
36
36
  @context.instance_exec(@result.value, &@ok)
37
- elsif Error === @result.error && fail_block = @fails[@result.error.type]
37
+ elsif Error === @result.error && (fail_block = @fails[@result.error.type])
38
38
  @context.instance_exec(@result.error, &fail_block)
39
39
  else
40
40
  @context.instance_exec(@result.error, &@fail_default)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sequel/model'
3
+ require "sequel/model"
4
4
 
5
5
  module Pathway
6
6
  module Plugins
@@ -32,9 +32,10 @@ module Pathway
32
32
 
33
33
  def _opts_if_unless(bg) = %i[if unless].map { bg.local_variable_get(_1) }
34
34
 
35
- def _with_db_steps(steps, step_name=nil, if_cond=nil, unless_cond=nil, &db_logic)
36
- raise ArgumentError, 'options :if and :unless are mutually exclusive' if if_cond && unless_cond
37
- raise ArgumentError, 'must provide either a step or a block but not both' if !!step_name == !!steps
35
+ def _with_db_steps(steps, step_name = nil, if_cond = nil, unless_cond = nil, &db_logic)
36
+ raise ArgumentError, "options :if and :unless are mutually exclusive" if if_cond && unless_cond
37
+ raise ArgumentError, "must provide either a step or a block but not both" if !step_name.nil? == !steps.nil?
38
+
38
39
  steps ||= proc { step step_name }
39
40
 
40
41
  if if_cond
@@ -69,15 +70,16 @@ module Pathway
69
70
 
70
71
  module InstanceMethods
71
72
  extend Forwardable
72
- delegate %i[model_class search_field model_not_found] => 'self.class'
73
- delegate :db => :model_class
74
73
 
75
- def fetch_model(state, from: model_class, search_by: search_field, using: search_by, to: result_key, overwrite: false, error_message: nil)
76
- error_message ||= if (from == model_class)
74
+ delegate %i[model_class search_field model_not_found] => "self.class"
75
+ delegate db: :model_class
76
+
77
+ def fetch_model(state, from: model_class, search_by: search_field, using: search_by, to: result_key, overwrite: false, error_message: nil) # rubocop:disable Metrics/ParameterLists
78
+ error_message ||= if from == model_class
77
79
  model_not_found
78
80
  elsif from.respond_to?(:name) || from.respond_to?(:model)
79
81
  from_name = (from.respond_to?(:name) ? from : from.model).name
80
- Inflector.humanize(Inflector.underscore(Inflector.demodulize(from_name))) + ' not found'
82
+ Inflector.humanize(Inflector.underscore(Inflector.demodulize(from_name))) + " not found"
81
83
  end
82
84
 
83
85
  if state[to].nil? || overwrite
@@ -94,8 +96,8 @@ module Pathway
94
96
  end
95
97
  end
96
98
 
97
- def self.apply(operation, model: nil, **kwargs)
98
- operation.model(model, **kwargs) if model
99
+ def self.apply(operation, model: nil, **)
100
+ operation.model(model, **) if model
99
101
  end
100
102
  end
101
103
  end
@@ -3,14 +3,15 @@
3
3
  module Pathway
4
4
  class Result
5
5
  extend Forwardable
6
+
6
7
  attr_reader :value, :error
7
8
 
8
9
  class Success < Result
9
10
  def initialize(value) = @value = value
10
11
  def success? = true
11
12
 
12
- def then(bl=nil)
13
- result(block_given? ? yield(value): bl.call(value))
13
+ def then(bl = nil)
14
+ result(block_given? ? yield(value) : bl.call(value))
14
15
  end
15
16
 
16
17
  def tee(...)
@@ -18,20 +19,16 @@ module Pathway
18
19
  follow.failure? ? follow : self
19
20
  end
20
21
 
21
- private
22
-
23
- alias_method :value_for_deconstruct, :value
22
+ private alias_method :value_for_deconstruct, :value
24
23
  end
25
24
 
26
25
  class Failure < Result
27
26
  def initialize(error) = @error = error
28
27
  def success? = false
29
- def then(_=nil) = self
30
- def tee(_=nil) = self
31
-
32
- private
28
+ def then(_ = nil) = self
29
+ def tee(_ = nil) = self
33
30
 
34
- alias_method :value_for_deconstruct, :error
31
+ private alias_method :value_for_deconstruct, :error
35
32
  end
36
33
 
37
34
  module Mixin
@@ -57,6 +54,6 @@ module Pathway
57
54
  end
58
55
  end
59
56
 
60
- delegate :result => 'self.class'
57
+ delegate result: "self.class"
61
58
  end
62
59
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathway/rspec/matchers/form_schema_helpers'
3
+ require "pathway/rspec/matchers/form_schema_helpers"
4
4
 
5
5
  RSpec::Matchers.define :accept_optional_fields do |*fields|
6
6
  match do |form|
@@ -13,7 +13,7 @@ RSpec::Matchers.define :accept_optional_fields do |*fields|
13
13
  end
14
14
 
15
15
  match_when_negated do |form|
16
- raise NotImplementedError, 'expect().not_to accept_optional_fields.not_allowing_null_values is not supported.' if @allowing_null_values || @not_allowing_null_values
16
+ raise NotImplementedError, "expect().not_to accept_optional_fields.not_allowing_null_values is not supported." if @allowing_null_values || @not_allowing_null_values
17
17
 
18
18
  @form, @fields = form, fields
19
19
 
@@ -21,23 +21,23 @@ RSpec::Matchers.define :accept_optional_fields do |*fields|
21
21
  end
22
22
 
23
23
  description do
24
- null_value_allowed = @allowing_null_values ? ' allowing null values' : ''
25
- null_value_disallowed = @not_allowing_null_values ? ' not allowing null values' : ''
24
+ null_value_allowed = @allowing_null_values ? " allowing null values" : ""
25
+ null_value_disallowed = @not_allowing_null_values ? " not allowing null values" : ""
26
26
  "accept #{field_list} as optional #{pluralize_fields}#{null_value_allowed}#{null_value_disallowed}"
27
27
  end
28
28
 
29
29
  failure_message do
30
- null_value_allowed = @allowing_null_values ? ' allowing null values' : ''
31
- null_value_disallowed = @not_allowing_null_values ? ' not allowing null values' : ''
30
+ null_value_allowed = @allowing_null_values ? " allowing null values" : ""
31
+ null_value_disallowed = @not_allowing_null_values ? " not allowing null values" : ""
32
32
 
33
33
  "Expected to accept #{field_list} as optional #{pluralize_fields}#{null_value_allowed}#{null_value_disallowed} but " +
34
34
  as_sentence([not_optional_list, not_defined_list, accepting_null_list, not_accepting_null_list].compact,
35
- connector: '; ', last_connector: '; and ')
35
+ connector: "; ", last_connector: "; and ")
36
36
  end
37
37
 
38
38
  failure_message_when_negated do
39
39
  "Did not expect to accept #{field_list} as optional #{pluralize_fields} but " +
40
- [optional_list, not_defined_list].compact.join('; and ')
40
+ [optional_list, not_defined_list].compact.join("; and ")
41
41
  end
42
42
 
43
43
  include Pathway::Rspec::FormSchemaHelpers
@@ -51,13 +51,13 @@ RSpec::Matchers.define :accept_optional_fields do |*fields|
51
51
  end
52
52
 
53
53
  chain :allowing_null_values do
54
- fail 'cannot use allowing_null_values and not_allowing_null_values at the same time' if @not_allowing_null_values
54
+ raise "cannot use allowing_null_values and not_allowing_null_values at the same time" if @not_allowing_null_values
55
55
 
56
56
  @allowing_null_values = true
57
57
  end
58
58
 
59
59
  chain :not_allowing_null_values do
60
- fail 'cannot use allowing_null_values and not_allowing_null_values at the same time' if @allowing_null_values
60
+ raise "cannot use allowing_null_values and not_allowing_null_values at the same time" if @allowing_null_values
61
61
 
62
62
  @not_allowing_null_values = true
63
63
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathway/rspec/matchers/list_helpers'
3
+ require "pathway/rspec/matchers/list_helpers"
4
4
 
5
5
  RSpec::Matchers.define :fail_on do |input|
6
6
  match do |operation|
@@ -10,9 +10,10 @@ RSpec::Matchers.define :fail_on do |input|
10
10
  end
11
11
 
12
12
  match_when_negated do |operation|
13
- raise NotImplementedError, '`expect().not_to fail_on(input).with_type()` is not supported.' if @type
14
- raise NotImplementedError, '`expect().not_to fail_on(input).with_message()` is not supported.' if @message
15
- raise NotImplementedError, '`expect().not_to fail_on(input).with_details()` is not supported.' if @details
13
+ raise NotImplementedError, "`expect().not_to fail_on(input).with_type()` is not supported." if @type
14
+ raise NotImplementedError, "`expect().not_to fail_on(input).with_message()` is not supported." if @message
15
+ raise NotImplementedError, "`expect().not_to fail_on(input).with_details()` is not supported." if @details
16
+
16
17
  @operation, @input = operation, input
17
18
 
18
19
  !failure?
@@ -40,20 +41,20 @@ RSpec::Matchers.define :fail_on do |input|
40
41
  alias_method :and_details, :details
41
42
 
42
43
  description do
43
- 'fail' + (@type ? " with :#@type error" : '')
44
+ "fail" + (@type ? " with :#{@type} error" : "")
44
45
  end
45
46
 
46
47
  failure_message do
47
- if !failure?
48
- "Expected operation to fail but it didn't"
48
+ if failure?
49
+ "Expected failed operation to " +
50
+ as_sentence(failure_descriptions, connector: "; ", last_connector: "; and ")
49
51
  else
50
- 'Expected failed operation to ' +
51
- as_sentence(failure_descriptions, connector: '; ', last_connector: '; and ')
52
+ "Expected operation to fail but it didn't"
52
53
  end
53
54
  end
54
55
 
55
56
  failure_message_when_negated do
56
- 'Did not expected operation to fail but it did'
57
+ "Did not expected operation to fail but it did"
57
58
  end
58
59
 
59
60
  def failure?
@@ -85,7 +86,7 @@ RSpec::Matchers.define :fail_on do |input|
85
86
  end
86
87
 
87
88
  def type_failure_description
88
- type_matches? ? nil : "have type :#@type but instead was :#{error.type}"
89
+ type_matches? ? nil : "have type :#{@type} but instead was :#{error.type}"
89
90
  end
90
91
 
91
92
  def message_failure_description
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathway/rspec/matchers/list_helpers'
3
+ require "pathway/rspec/matchers/list_helpers"
4
4
 
5
5
  module Pathway
6
6
  module Rspec
@@ -12,11 +12,11 @@ module Pathway
12
12
  end
13
13
 
14
14
  def were_was(list)
15
- list.size > 1 ? 'were' : 'was'
15
+ list.size > 1 ? "were" : "was"
16
16
  end
17
17
 
18
18
  def pluralize_fields
19
- @fields.size > 1 ? 'fields' : 'field'
19
+ @fields.size > 1 ? "fields" : "field"
20
20
  end
21
21
  end
22
22
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathway/rspec/matchers/field_list_helpers'
3
+ require "pathway/rspec/matchers/field_list_helpers"
4
4
 
5
5
  module Pathway
6
6
  module Rspec
@@ -3,14 +3,14 @@
3
3
  module Pathway
4
4
  module Rspec
5
5
  module ListHelpers
6
- def as_list(items, **kwargs)
7
- as_sentence(items.map(&:inspect), **kwargs)
6
+ def as_list(items, **)
7
+ as_sentence(items.map(&:inspect), **)
8
8
  end
9
9
 
10
- def as_sentence(items, connector: ', ', last_connector: ' and ')
10
+ def as_sentence(items, connector: ", ", last_connector: " and ")
11
11
  *rest, last = items
12
12
 
13
- result = String.new
13
+ result = +""
14
14
  result << rest.join(connector) << last_connector if rest.any?
15
15
  result << last
16
16
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathway/rspec/matchers/form_schema_helpers'
3
+ require "pathway/rspec/matchers/form_schema_helpers"
4
4
 
5
5
  RSpec::Matchers.define :require_fields do |*fields|
6
6
  match do |form|
@@ -13,7 +13,7 @@ RSpec::Matchers.define :require_fields do |*fields|
13
13
  end
14
14
 
15
15
  match_when_negated do |form|
16
- raise NotImplementedError, 'expect().not_to require_fields.not_allowing_null_values is not supported.' if @allowing_null_values || @not_allowing_null_values
16
+ raise NotImplementedError, "expect().not_to require_fields.not_allowing_null_values is not supported." if @allowing_null_values || @not_allowing_null_values
17
17
 
18
18
  @form, @fields = form, fields
19
19
 
@@ -21,23 +21,23 @@ RSpec::Matchers.define :require_fields do |*fields|
21
21
  end
22
22
 
23
23
  description do
24
- null_value_allowed = @allowing_null_values ? ' allowing null values' : ''
25
- null_value_disallowed = @not_allowing_null_values ? ' not allowing null values' : ''
24
+ null_value_allowed = @allowing_null_values ? " allowing null values" : ""
25
+ null_value_disallowed = @not_allowing_null_values ? " not allowing null values" : ""
26
26
  "require #{field_list} as #{pluralize_fields}#{null_value_allowed}#{null_value_disallowed}"
27
27
  end
28
28
 
29
29
  failure_message do
30
- null_value_allowed = @allowing_null_values ? ' allowing null values' : ''
31
- null_value_disallowed = @not_allowing_null_values ? ' not allowing null values' : ''
30
+ null_value_allowed = @allowing_null_values ? " allowing null values" : ""
31
+ null_value_disallowed = @not_allowing_null_values ? " not allowing null values" : ""
32
32
 
33
33
  "Expected to require #{field_list} as #{pluralize_fields}#{null_value_allowed}#{null_value_disallowed} but " +
34
34
  as_sentence([not_required_list, not_defined_list, accepting_null_list, not_accepting_null_list].compact,
35
- connector: '; ', last_connector: '; and ')
35
+ connector: "; ", last_connector: "; and ")
36
36
  end
37
37
 
38
38
  failure_message_when_negated do
39
39
  "Did not expect to require #{field_list} as #{pluralize_fields} but " +
40
- [required_list, not_defined_list].compact.join('; and ')
40
+ [required_list, not_defined_list].compact.join("; and ")
41
41
  end
42
42
 
43
43
  include Pathway::Rspec::FormSchemaHelpers
@@ -51,13 +51,13 @@ RSpec::Matchers.define :require_fields do |*fields|
51
51
  end
52
52
 
53
53
  chain :allowing_null_values do
54
- fail 'cannot use allowing_null_values and not_allowing_null_values at the same time' if @not_allowing_null_values
54
+ raise "cannot use allowing_null_values and not_allowing_null_values at the same time" if @not_allowing_null_values
55
55
 
56
56
  @allowing_null_values = true
57
57
  end
58
58
 
59
59
  chain :not_allowing_null_values do
60
- fail 'cannot use allowing_null_values and not_allowing_null_values at the same time' if @allowing_null_values
60
+ raise "cannot use allowing_null_values and not_allowing_null_values at the same time" if @allowing_null_values
61
61
 
62
62
  @not_allowing_null_values = true
63
63
  end
@@ -8,7 +8,8 @@ RSpec::Matchers.define :succeed_on do |input|
8
8
  end
9
9
 
10
10
  match_when_negated do |operation|
11
- raise NotImplementedError, '`expect().not_to succeed_on(input).returning()` is not supported.' if @value
11
+ raise NotImplementedError, "`expect().not_to succeed_on(input).returning()` is not supported." if @value
12
+
12
13
  @operation, @input = operation, input
13
14
 
14
15
  !success?
@@ -23,15 +24,15 @@ RSpec::Matchers.define :succeed_on do |input|
23
24
  end
24
25
 
25
26
  failure_message do
26
- if !success?
27
- "Expected operation to be successful but failed with :#{result.error.type} error"
28
- else
27
+ if success?
29
28
  "Expected successful operation to return #{description_of(@value)} but instead got #{description_of(result.value)}"
29
+ else
30
+ "Expected operation to be successful but failed with :#{result.error.type} error"
30
31
  end
31
32
  end
32
33
 
33
34
  failure_message_when_negated do
34
- 'Did not to expected operation to be successful but it was'
35
+ "Did not to expected operation to be successful but it was"
35
36
  end
36
37
 
37
38
  def success?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathway/rspec/matchers/succeed_on'
4
- require 'pathway/rspec/matchers/fail_on'
5
- require 'pathway/rspec/matchers/accept_optional_fields'
6
- require 'pathway/rspec/matchers/require_fields'
3
+ require "pathway/rspec/matchers/succeed_on"
4
+ require "pathway/rspec/matchers/fail_on"
5
+ require "pathway/rspec/matchers/accept_optional_fields"
6
+ require "pathway/rspec/matchers/require_fields"
data/lib/pathway/rspec.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathway/rspec/matchers'
3
+ require "pathway/rspec/matchers"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pathway
4
- VERSION = '1.2.0'
4
+ VERSION = "1.3.0"
5
5
  end
data/lib/pathway.rb CHANGED
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
4
- require 'dry/inflector'
5
- require 'contextualizer'
6
- require 'pathway/version'
7
- require 'pathway/result'
3
+ require "forwardable"
4
+ require "dry/inflector"
5
+ require "contextualizer"
6
+ require "pathway/version"
7
+ require "pathway/result"
8
8
 
9
9
  module Pathway
10
10
  Inflector = Dry::Inflector.new
11
11
  class Operation
12
12
  class << self
13
- def plugin(name,...)
13
+ def plugin(name, ...)
14
14
  require "pathway/plugins/#{Inflector.underscore(name)}" if name.is_a?(Symbol)
15
15
 
16
16
  plugin = name.is_a?(Module) ? name : Plugins.const_get(Inflector.camelize(name))
@@ -19,7 +19,7 @@ module Pathway
19
19
  self.include plugin::InstanceMethods if plugin.const_defined? :InstanceMethods
20
20
  self::DSL.include plugin::DSLMethods if plugin.const_defined? :DSLMethods
21
21
 
22
- plugin.apply(self,...) if plugin.respond_to?(:apply)
22
+ plugin.apply(self, ...) if plugin.respond_to?(:apply)
23
23
  end
24
24
 
25
25
  def inherited(subclass)
@@ -34,6 +34,7 @@ module Pathway
34
34
 
35
35
  class Error
36
36
  attr_reader :type, :message, :details
37
+
37
38
  singleton_class.send :attr_accessor, :default_messages
38
39
 
39
40
  @default_messages = {}
@@ -56,7 +57,8 @@ module Pathway
56
57
 
57
58
  class State
58
59
  extend Forwardable
59
- delegate %i([] []= fetch store include? values_at deconstruct_keys) => :@hash
60
+
61
+ delegate %i[[] []= fetch store include? values_at deconstruct_keys] => :@hash
60
62
 
61
63
  def initialize(operation, values = {})
62
64
  @hash = operation.context.merge(values)
@@ -72,16 +74,16 @@ module Pathway
72
74
  def to_hash = @hash
73
75
 
74
76
  def use(&bl)
75
- raise ArgumentError, 'a block must be provided' if !block_given?
76
- if bl.parameters in [*, [:rest|:keyrest,], *]
77
- raise ArgumentError, 'rest arguments are not supported'
77
+ raise ArgumentError, "a block must be provided" unless block_given?
78
+ if bl.parameters in [*, [:rest | :keyrest,], *]
79
+ raise ArgumentError, "rest arguments are not supported"
78
80
  end
79
81
 
80
- keys = bl.parameters.select { _1 in :key|:keyreq, }.map(&:last)
81
- names = bl.parameters.select { _1 in :req|:opt, }.map(&:last)
82
+ keys = bl.parameters.select { _1 in :key | :keyreq, }.map(&:last)
83
+ names = bl.parameters.select { _1 in :req | :opt, }.map(&:last)
82
84
 
83
85
  if keys.any? && names.any?
84
- raise ArgumentError, 'cannot mix positional and keyword arguments'
86
+ raise ArgumentError, "cannot mix positional and keyword arguments"
85
87
  elsif keys.any?
86
88
  bl.call(**to_hash.slice(*keys))
87
89
  else
@@ -104,12 +106,12 @@ module Pathway
104
106
  def process(&steps)
105
107
  define_method(:call) do |input|
106
108
  _dsl_for(input:)
107
- .run(&steps)
108
- .then(&:result)
109
+ .run(&steps)
110
+ .then(&:result)
109
111
  end
110
112
  end
111
113
 
112
- def call(ctx,...) = new(ctx).call(...)
114
+ def call(ctx, ...) = new(ctx).call(...)
113
115
 
114
116
  def inherited(subclass)
115
117
  super
@@ -120,12 +122,12 @@ module Pathway
120
122
  module InstanceMethods
121
123
  extend Forwardable
122
124
 
123
- delegate :result_key => 'self.class'
125
+ delegate result_key: "self.class"
124
126
  delegate %i[result success failure] => Result
125
127
 
126
128
  alias_method :wrap, :result
127
129
 
128
- def call(*) = raise 'must implement at subclass'
130
+ def call(*) = raise "must implement at subclass"
129
131
 
130
132
  def error(type, message: nil, details: nil)
131
133
  failure(Error.new(type:, message:, details:))
@@ -150,46 +152,27 @@ module Pathway
150
152
  @result, @operation = wrap(state), operation
151
153
  end
152
154
 
153
- def run(&steps)
154
- instance_eval(&steps)
155
+ def run(&)
156
+ instance_eval(&)
155
157
  @result
156
158
  end
157
159
 
158
160
  # Execute step and preserve the former state
159
- def step(callable,...)
160
- #:nocov:
161
- if block_given?
162
- warn "[DEPRECATION] Passing a block to the step method using `DSLMethods#step` is deprecated"
163
- end
164
- #:nocov:
161
+ def step(callable, *, **)
165
162
  bl = _callable(callable)
166
- @result = @result.tee { |state| bl.call(state,...) }
163
+ @result = @result.tee { |state| bl.call(state, *, **) }
167
164
  end
168
165
 
169
166
  # Execute step and modify the former state setting the key
170
- def set(callable, *args, to: @operation.result_key, **kwargs, &bl)
171
- #:nocov:
172
- if block_given?
173
- warn "[DEPRECATION] Passing a block to the step method using `DSLMethods#set` is deprecated"
174
- end
175
- #:nocov:
167
+ def set(callable, *args, to: @operation.result_key, **kwargs)
176
168
  bl = _callable(callable)
177
169
 
178
170
  @result = @result.then do |state|
179
- wrap(bl.call(state, *args, **kwargs, &bl))
171
+ wrap(bl.call(state, *args, **kwargs))
180
172
  .then { |value| state.update(to => value) }
181
173
  end
182
174
  end
183
175
 
184
- # Execute step and replace the current state completely
185
- def map(callable,...)
186
- #:nocov:
187
- warn "[DEPRECATION] `Pathway::DSLMethods#map` has been deprecated, use `step` instead"
188
- #:nocov:
189
- bl = _callable(callable)
190
- @result = @result.then { |state| bl.call(state,...) }
191
- end
192
-
193
176
  def around(execution_strategy, &steps)
194
177
  @result.then do |state|
195
178
  steps_runner = ->(dsl = self) { dsl.run(&steps) }
@@ -198,13 +181,13 @@ module Pathway
198
181
  end
199
182
  end
200
183
 
201
- def if_true(cond, &steps)
184
+ def if_true(cond, &)
202
185
  cond = _callable(cond)
203
- around(->(runner, state) { runner.call if cond.call(state) }, &steps)
186
+ around(->(runner, state) { runner.call if cond.call(state) }, &)
204
187
  end
205
188
 
206
- def if_false(cond, &steps)
207
- if_true(_callable(cond) >> :!.to_proc, &steps)
189
+ def if_false(cond, &)
190
+ if_true(_callable(cond) >> :!.to_proc, &)
208
191
  end
209
192
 
210
193
  alias_method :sequence, :around
data/pathway.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path("../lib", __FILE__)
3
+ lib = File.expand_path("lib", __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require "pathway/version"
6
6
 
@@ -10,24 +10,23 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ["Pablo Herrero"]
11
11
  spec.email = ["pablodherrero@gmail.com"]
12
12
 
13
- spec.summary = %q{Define your business logic in simple steps.}
14
- spec.description = %q{Define your business logic in simple steps.}
13
+ spec.summary = "Define your business logic in simple steps."
14
+ spec.description = "Define your business logic in simple steps."
15
15
  spec.homepage = "https://github.com/pabloh/pathway"
16
16
  spec.license = "MIT"
17
17
 
18
18
  spec.metadata = {
19
- "bug_tracker_uri" => "https://github.com/pabloh/pathway/issues",
20
- "source_code_uri" => "https://github.com/pabloh/pathway",
19
+ "rubygems_mfa_required" => "true",
20
+ "bug_tracker_uri" => "https://github.com/pabloh/pathway/issues",
21
+ "source_code_uri" => "https://github.com/pabloh/pathway",
21
22
  }
22
23
 
23
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
24
- f.match(%r{^(test|spec|features)/})
25
- end
24
+ spec.files = `git ls-files -z`.split("\x0").grep_v(%r{^(test|spec|features)/})
26
25
  spec.bindir = "exe"
27
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
27
  spec.require_paths = ["lib"]
29
28
 
30
- spec.required_ruby_version = ">= 3.2.0"
29
+ spec.required_ruby_version = ">= 3.3.0"
31
30
 
32
31
  spec.add_dependency "dry-inflector", ">= 0.1.0"
33
32
  spec.add_dependency "contextualizer", "~> 0.1.0"
@@ -37,7 +36,10 @@ Gem::Specification.new do |spec|
37
36
  spec.add_development_dependency "sequel", "~> 5.0"
38
37
  spec.add_development_dependency "rake", "~> 13.0"
39
38
  spec.add_development_dependency "rspec", "~> 3.11"
40
- spec.add_development_dependency "simplecov-lcov", '~> 0.8.0'
39
+ spec.add_development_dependency "simplecov-lcov", "~> 0.8.0"
40
+ spec.add_development_dependency "rubocop", "~> 1.81.0"
41
+ spec.add_development_dependency "rubocop-performance"
42
+ spec.add_development_dependency "rubocop-rake"
41
43
  spec.add_development_dependency "simplecov"
42
44
  spec.add_development_dependency "pry"
43
45
  spec.add_development_dependency "reline"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pathway
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pablo Herrero
@@ -121,6 +121,48 @@ dependencies:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
123
  version: 0.8.0
124
+ - !ruby/object:Gem::Dependency
125
+ name: rubocop
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 1.81.0
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 1.81.0
138
+ - !ruby/object:Gem::Dependency
139
+ name: rubocop-performance
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ - !ruby/object:Gem::Dependency
153
+ name: rubocop-rake
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'
124
166
  - !ruby/object:Gem::Dependency
125
167
  name: simplecov
126
168
  requirement: !ruby/object:Gem::Requirement
@@ -215,6 +257,7 @@ files:
215
257
  - ".github/workflows/tests.yml"
216
258
  - ".gitignore"
217
259
  - ".rspec"
260
+ - ".rubocop.yml"
218
261
  - CHANGELOG.md
219
262
  - Gemfile
220
263
  - LICENSE.txt
@@ -229,16 +272,20 @@ files:
229
272
  - bin/irb
230
273
  - bin/ldiff
231
274
  - bin/pry
275
+ - bin/racc
232
276
  - bin/rake
233
277
  - bin/rbs
234
278
  - bin/rdbg
235
279
  - bin/rdoc
236
280
  - bin/ri
237
281
  - bin/rspec
282
+ - bin/rubocop
238
283
  - bin/ruby-lsp
239
284
  - bin/ruby-lsp-check
240
285
  - bin/ruby-lsp-launcher
241
286
  - bin/ruby-lsp-test-exec
287
+ - bin/ruby-parse
288
+ - bin/ruby-rewrite
242
289
  - bin/sequel
243
290
  - bin/setup
244
291
  - bin/yard
@@ -266,6 +313,7 @@ homepage: https://github.com/pabloh/pathway
266
313
  licenses:
267
314
  - MIT
268
315
  metadata:
316
+ rubygems_mfa_required: 'true'
269
317
  bug_tracker_uri: https://github.com/pabloh/pathway/issues
270
318
  source_code_uri: https://github.com/pabloh/pathway
271
319
  rdoc_options: []
@@ -275,14 +323,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
275
323
  requirements:
276
324
  - - ">="
277
325
  - !ruby/object:Gem::Version
278
- version: 3.2.0
326
+ version: 3.3.0
279
327
  required_rubygems_version: !ruby/object:Gem::Requirement
280
328
  requirements:
281
329
  - - ">="
282
330
  - !ruby/object:Gem::Version
283
331
  version: '0'
284
332
  requirements: []
285
- rubygems_version: 3.6.9
333
+ rubygems_version: 4.0.3
286
334
  specification_version: 4
287
335
  summary: Define your business logic in simple steps.
288
336
  test_files: []