dry-matcher 0.7.0 → 0.8.0

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: a452c874d6095df3fd8a932dfc0a604fa2ef531dff6ca30ee2c850f1012ce13c
4
- data.tar.gz: 8a061065d80d1821fdb4e9b020050cd380ee69a73af6351bbc78bfeab5153911
3
+ metadata.gz: 0cceeb633b3e3e6136ff03e886149d54d55e483256cfa591a8b47f5cedf832fb
4
+ data.tar.gz: 67afc05d71891776a2f0f2897cfddd45e1741cf837c46c5d1a2c26740f98851a
5
5
  SHA512:
6
- metadata.gz: 8af536933244d441747638bcf7244f1918c4cb626717d48be1087704628f0c3b09266e6b55917fd18b776a464eaae4fc25e8382e22b661d3f408dc99c69c93bf
7
- data.tar.gz: 5ca949c319b53001db633bdf6493eb2f99ab27bea4171b3429523991f9c3063ef5edceb3a5ee068ec75f9af5269f0795d7d09d1b03437d57cbdfee2e6fd8e8b3
6
+ metadata.gz: 5f22821845ef6e4e22d23328870a577c2fc0e8861627a7f2718378f7938e00aed9bc106e0917390556efeebd56584bccd933f41f09f4496a99ee7eb28012257a
7
+ data.tar.gz: 184881702b0e743cf991cee0a3e0fef9870da4775fdcd705647c83dd9a12afd844eb481b8a5eca636ec9b205989a8433156916d2c9bd2462d363736d3d23316b
@@ -0,0 +1,15 @@
1
+ version: "2"
2
+
3
+ prepare:
4
+ fetch:
5
+ - url: "https://raw.githubusercontent.com/dry-rb/devtools/master/.rubocop.yml"
6
+ path: ".rubocop.yml"
7
+
8
+ exclude_patterns:
9
+ - "benchmarks/"
10
+ - "examples/"
11
+ - "spec/"
12
+
13
+ plugins:
14
+ rubocop:
15
+ enabled: true
@@ -0,0 +1,6 @@
1
+ /Gemfile.lock
2
+ /.yardoc
3
+ /doc
4
+ /coverage
5
+ /spec/examples.txt
6
+ /pkg
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+ cache: bundler
3
+ bundler_args: --without tools
4
+ before_script:
5
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
6
+ - chmod +x ./cc-test-reporter
7
+ - ./cc-test-reporter before-build
8
+ after_script:
9
+ - "[ -d coverage ] && ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
10
+ rvm:
11
+ - 2.4.6
12
+ - 2.5.5
13
+ - 2.6.3
14
+ - jruby-9.2.7.0
15
+ env:
16
+ global:
17
+ - COVERAGE=true
18
+ - JRUBY_OPTS='--dev -J-Xmx1024M'
19
+ notifications:
20
+ email: false
@@ -0,0 +1 @@
1
+ --markup=markdown
@@ -1,4 +1,46 @@
1
- # 0.7.0 / to-be-released
1
+ # 0.8.0 / 2019-07-30
2
+
3
+ ## Changed
4
+
5
+ - [BREAKING] Support for Ruby 2.3 was dropped as it's EOL
6
+
7
+ ## Added
8
+
9
+ - API for cases was changed to work with a single block instead of `match`/`resolve` combination (flash-gordon in [#23](https://github.com/dry-rb/dry-matcher/pull/23)):
10
+ ```ruby
11
+ Dry::Matcher::Case.new do |value, patterns|
12
+ if patterns.include?(value)
13
+ # value will be passed to the block
14
+ value
15
+ else
16
+ # Undefined stands for no match
17
+ Dry::Matcher::Undefined
18
+ end
19
+ end
20
+ ```
21
+ - `ResultMatcher` now uses patterns for matching and matches against the first element if an array is passed (flash-gordon in [#24](https://github.com/dry-rb/dry-matcher/pull/24) and [#22](https://github.com/dry-rb/dry-matcher/pull/22) and michaelherold in [#21](https://github.com/dry-rb/dry-matcher/pull/21))
22
+
23
+ ```ruby
24
+ value = Dry::Monads::Result::Failure.new([:invalid, :reasons])
25
+
26
+ Dry::Matcher::ResultMatcher.(value) do |m|
27
+ m.success do |v|
28
+ "Yay: #{v}"
29
+ end
30
+
31
+ m.failure(:not_found) do
32
+ "No such thing"
33
+ end
34
+
35
+ m.failure(:invalid) do |_code, errors|
36
+ "Cannot be done: #{errors.inspect}"
37
+ end
38
+ end #=> "Cannot be done: :reasons"
39
+ ```
40
+
41
+ [Compare v0.7.0...v0.8.0](https://github.com/dry-rb/dry-matcher/compare/v0.7.0...v0.8.0)
42
+
43
+ # 0.7.0 / 2018-01-11
2
44
 
3
45
  ## Changed
4
46
 
@@ -29,59 +71,60 @@
29
71
 
30
72
  - Added support for building custom matchers, with an any number of match cases, each offering their own matching and resolving logic. This is now the primary API for dry-matcher. (timriley)
31
73
 
32
- ```ruby
33
- # Match `[:ok, some_value]` for success
34
- success_case = Dry::Matcher::Case.new(
35
- match: -> value { value.first == :ok },
36
- resolve: -> value { value.last }
37
- )
38
-
39
- # Match `[:err, some_error_code, some_value]` for failure
40
- failure_case = Dry::Matcher::Case.new(
41
- match: -> value, *pattern {
42
- value[0] == :err && (pattern.any? ? pattern.include?(value[1]) : true)
43
- },
44
- resolve: -> value { value.last }
45
- )
46
-
47
- # Build the matcher
48
- matcher = Dry::Matcher.new(success: success_case, failure: failure_case)
49
-
50
- # Then put it to use
51
- my_success = [:ok, "success!"]
52
-
53
- result = matcher.(my_success) do |m|
54
- m.success do |v|
55
- "Yay: #{v}"
56
- end
57
-
58
- m.failure :not_found do |v|
59
- "Oops, not found: #{v}"
60
- end
61
-
62
- m.failure do |v|
63
- "Boo: #{v}"
64
- end
74
+ ```ruby
75
+ # Match `[:ok, some_value]` for success
76
+ success_case = Dry::Matcher::Case.new(
77
+ match: -> value { value.first == :ok },
78
+ resolve: -> value { value.last }
79
+ )
80
+
81
+ # Match `[:err, some_error_code, some_value]` for failure
82
+ failure_case = Dry::Matcher::Case.new(
83
+ match: -> value, *pattern {
84
+ value[0] == :err && (pattern.any? ? pattern.include?(value[1]) : true)
85
+ },
86
+ resolve: -> value { value.last }
87
+ )
88
+
89
+ # Build the matcher
90
+ matcher = Dry::Matcher.new(success: success_case, failure: failure_case)
91
+
92
+ # Then put it to use
93
+ my_success = [:ok, "success!"]
94
+
95
+ result = matcher.(my_success) do |m|
96
+ m.success do |v|
97
+ "Yay: #{v}"
65
98
  end
66
99
 
67
- result # => "Yay: success!"
68
- ```
100
+ m.failure :not_found do |v|
101
+ "Oops, not found: #{v}"
102
+ end
103
+
104
+ m.failure do |v|
105
+ "Boo: #{v}"
106
+ end
107
+ end
108
+
109
+ result # => "Yay: success!"
110
+ ```
69
111
 
70
112
  ## Changed
71
113
 
72
114
  - Renamed to `dry-matcher`, since this is now a flexible, general purpose pattern matching API. All components are now available under the `Dry::Matcher` namespace. (timriley)
73
115
  - `Dry::Matcher.for` requires a matcher object to be passed when being included in a class:
74
116
 
75
- ```ruby
76
- MyMatcher = Dry::Matcher.new(...)
117
+ ```ruby
118
+ MyMatcher = Dry::Matcher.new(...)
77
119
 
78
- class MyOperation
79
- include Dry::Matcher.for(:call, with: MyMatcher)
120
+ class MyOperation
121
+ include Dry::Matcher.for(:call, with: MyMatcher)
80
122
 
81
- def call
82
- end
123
+ def call
83
124
  end
84
- ```
125
+ end
126
+ ```
127
+
85
128
  - The previous `Dry::ResultMatcher.match` behaviour (for matching `Either` monads) has been moved to `Dry::Matcher::EitherMatcher.call`
86
129
 
87
130
  [Compare v0.4.0...v0.5.0](https://github.com/dry-rb/dry-matcher/compare/v0.4.0...v0.5.0)
@@ -90,11 +133,11 @@
90
133
 
91
134
  ## Added
92
135
 
93
- * Support convertible result objects responding to `#to_either` (ttdonovan)
136
+ - Support convertible result objects responding to `#to_either` (ttdonovan)
94
137
 
95
138
  ## Changed
96
139
 
97
- * Expect monads from [dry-monads](https://github.com/dry-rb/dry-monads) instead of [Kleisli](https://github.com/txus/kleisli) (ttdonovan)
140
+ - Expect monads from [dry-monads](https://github.com/dry-rb/dry-monads) instead of [Kleisli](https://github.com/txus/kleisli) (ttdonovan)
98
141
 
99
142
  [Compare v0.3.0...v0.4.0](https://github.com/dry-rb/dry-matcher/compare/v0.3.0...v0.4.0)
100
143
 
@@ -102,7 +145,7 @@
102
145
 
103
146
  ## Changed
104
147
 
105
- * Renamed to `dry-result_matcher`. Match results using `Dry::ResultMatcher.match` or extend your own classes with `Dry::ResultMatcher.for`.
148
+ - Renamed to `dry-result_matcher`. Match results using `Dry::ResultMatcher.match` or extend your own classes with `Dry::ResultMatcher.for`.
106
149
 
107
150
  [Compare v0.2.0...v0.3.0](https://github.com/dry-rb/dry-matcher/compare/v0.2.0...v0.3.0)
108
151
 
@@ -110,7 +153,7 @@
110
153
 
111
154
  ## Added
112
155
 
113
- * Added `EitherResultMatcher.for(*methods)` to return a module wrapping the specified methods (returning an `Either`) with the match block API. Example usage, in a class with a `#call` method: `include EitherResultMatcher.for(:call)`.
156
+ - Added `EitherResultMatcher.for(*methods)` to return a module wrapping the specified methods (returning an `Either`) with the match block API. Example usage, in a class with a `#call` method: `include EitherResultMatcher.for(:call)`.
114
157
 
115
158
  [Compare v0.1.0...v0.22.0](https://github.com/dry-rb/dry-matcher/compare/v0.1.0...v0.2.0)
116
159
 
data/Gemfile CHANGED
@@ -1,14 +1,22 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  gemspec
4
6
 
7
+ gem 'bundler'
8
+ gem 'rake'
9
+ gem 'yard'
10
+
5
11
  group :test do
6
- gem "simplecov"
7
- gem "codeclimate-test-reporter"
8
- gem "dry-monads", '>= 0.4.0'
12
+ gem 'codeclimate-test-reporter'
13
+ gem 'dry-monads', '~> 1.2.0'
14
+ gem 'rspec', '~> 3.8'
15
+ gem 'simplecov'
9
16
  end
10
17
 
11
18
  group :tools do
12
- gem "byebug", platform: :mri
13
- gem "pry"
19
+ gem 'byebug', platform: :mri
20
+ gem 'pry'
21
+ gem 'rubocop', require: false
14
22
  end
data/README.md CHANGED
@@ -1,22 +1,24 @@
1
1
  [gitter]: https://gitter.im/dry-rb/chat
2
2
  [gem]: https://rubygems.org/gems/dry-matcher
3
- [travis]: https://travis-ci.org/dry-rb/dry-matcher
4
- [code_climate]: https://codeclimate.com/github/dry-rb/dry-matcher
3
+ [travis]: https://travis-ci.com/dry-rb/dry-matcher
4
+ [chat]: https://dry-rb.zulipchat.com
5
5
  [inch]: http://inch-ci.org/github/dry-rb/dry-matcher
6
+ [codeclimate]: https://codeclimate.com/github/dry-rb/dry-matcher/maintainability
7
+ [coverage]: https://codeclimate.com/github/dry-rb/dry-matcher/test_coverage
6
8
 
7
- # dry-matcher [![Join the Gitter chat](https://badges.gitter.im/Join%20Chat.svg)][gitter]
9
+ # dry-matcher [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
8
10
 
9
11
  [![Gem Version](https://img.shields.io/gem/v/dry-matcher.svg)][gem]
10
12
  [![Build Status](https://img.shields.io/travis/dry-rb/dry-matcher.svg)][travis]
11
- [![Code Climate](https://img.shields.io/codeclimate/github/dry-rb/dry-matcher.svg)][code_climate]
12
- [![Test Coverage](https://img.shields.io/codeclimate/coverage/github/dry-rb/dry-matcher.svg)][code_climate]
13
+ [![Maintainability](https://api.codeclimate.com/v1/badges/6765625216f301c617eb/maintainability)][codeclimate]
14
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/6765625216f301c617eb/test_coverage)][coverage]
13
15
  [![API Documentation Coverage](http://inch-ci.org/github/dry-rb/dry-matcher.svg)][inch]
14
16
 
15
17
  Flexible, expressive pattern matching for Ruby.
16
18
 
17
19
  ## Links
18
20
 
19
- * [Documentation](http://dry-rb.org/gems/dry-matcher)
21
+ - [Documentation](http://dry-rb.org/gems/dry-matcher)
20
22
 
21
23
  ## License
22
24
 
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
2
 
3
- require "rspec/core/rake_task"
3
+ require 'bundler/gem_tasks'
4
+
5
+ require 'rspec/core/rake_task'
4
6
  RSpec::Core::RakeTask.new
5
7
 
6
8
  task default: :spec
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'dry/matcher/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'dry-matcher'
9
+ spec.version = Dry::Matcher::VERSION
10
+ spec.authors = ['Tim Riley', 'Nikita Shilnikov']
11
+ spec.email = ['tim@icelab.com.au', 'fg@flashgordon.ru']
12
+ spec.license = 'MIT'
13
+
14
+ spec.summary = 'Flexible, expressive pattern matching for Ruby'
15
+ spec.description = spec.summary
16
+ spec.homepage = 'http://dry-rb.org/gems/dry-matcher'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|bin)/}) }
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.required_ruby_version = '>= 2.4.0'
24
+
25
+ spec.add_runtime_dependency 'dry-core', '>= 0.4.7'
26
+ end
@@ -1 +1,3 @@
1
- require "dry/matcher"
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/matcher'
@@ -1,9 +1,14 @@
1
- require "dry/matcher/case"
2
- require "dry/matcher/evaluator"
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/core/constants'
4
+ require 'dry/matcher/case'
5
+ require 'dry/matcher/evaluator'
3
6
 
4
7
  module Dry
5
8
  # @see http://dry-rb.org/gems/dry-matcher
6
9
  class Matcher
10
+ include Core::Constants
11
+
7
12
  # Generates a module containing pattern matching for methods listed in
8
13
  # `match_methods` argument with behavior defined by `with` matcher
9
14
  #
@@ -70,7 +75,7 @@ module Dry
70
75
  # after matched pattern
71
76
  #
72
77
  # @example Usage with `dry-monads`
73
- # require 'dry-monads'
78
+ # require 'dry/monads/result'
74
79
  # require 'dry/matcher/result_matcher'
75
80
  #
76
81
  # value = Dry::Monads::Result::Failure.new('failure!')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  class Matcher
3
5
  # {Case} object contains logic for pattern matching and resolving result
@@ -7,29 +9,27 @@ module Dry
7
9
 
8
10
  # @param match [#call] callable used to test given pattern against value
9
11
  # @param resolve [#call] callable used to resolve value into a result
10
- def initialize(match:, resolve: DEFAULT_RESOLVE)
11
- @match = match
12
- @resolve = resolve
13
- end
14
-
15
- # Tests whether `value` (with optional `*pattern`) matches pattern using
16
- # callable given to {#initialize} as `match:` argument
17
- #
18
- # @param [Object] value
19
- # @param [<Object>] pattern optional pattern given after the `value` to
20
- # `match:` callable
21
- # @return [Boolean]
22
- def matches?(value, *pattern)
23
- @match.(value, *pattern)
12
+ def initialize(match: Undefined, resolve: DEFAULT_RESOLVE, &block)
13
+ if block
14
+ @match = block
15
+ else
16
+ @match = proc do |value, patterns|
17
+ if match.(value, *patterns)
18
+ resolve.(value)
19
+ else
20
+ Undefined
21
+ end
22
+ end
23
+ end
24
24
  end
25
25
 
26
- # Resolves result from `value` using callable given to {#initialize}
27
- # as `resolve:` argument
28
- #
29
- # @param [Object] value
30
- # @return [Object] result resolved from given `value`
31
- def resolve(value)
32
- @resolve.(value)
26
+ # @param [Object] value Value to match
27
+ # @param [Array<Object>] patterns Optional list of patterns to match against
28
+ # @yieldparam [Object] v Resolved value if match succeeds
29
+ # @return [Object,Dry::Core::Constants::Undefined] Either the yield result
30
+ # or Undefined if match wasn't successful
31
+ def call(value, patterns = EMPTY_ARRAY, &block)
32
+ Undefined.map(@match.(value, patterns), &block)
33
33
  end
34
34
  end
35
35
  end
@@ -1,7 +1,14 @@
1
- require "dry/matcher/result_matcher"
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/core/deprecations'
4
+ require 'dry/matcher/result_matcher'
2
5
 
3
6
  module Dry
4
7
  class Matcher
8
+ extend Dry::Core::Deprecations[:'dry-matcher']
9
+
5
10
  EitherMatcher = ResultMatcher
11
+
12
+ deprecate_constant(:EitherMatcher, message: 'Dry::Matcher::ResultMatcher')
6
13
  end
7
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  class Matcher
3
5
  NonExhaustiveMatchError = Class.new(StandardError)
@@ -11,8 +13,6 @@ module Dry
11
13
  @result = result
12
14
 
13
15
  @unhandled_cases = @cases.keys.map(&:to_sym)
14
- @matched = false
15
- @output = nil
16
16
  end
17
17
 
18
18
  def call
@@ -20,14 +20,14 @@ module Dry
20
20
 
21
21
  ensure_exhaustive_match
22
22
 
23
- @output
23
+ @output if defined? @output
24
24
  end
25
25
 
26
26
  # Checks whether `cases` given to {#initialize} contains one called `name`
27
27
  # @param [String] name
28
28
  # @param [Boolean] include_private
29
29
  # @return [Boolean]
30
- def respond_to_missing?(name, include_private = false)
30
+ def respond_to_missing?(name, _include_private = false)
31
31
  @cases.key?(name)
32
32
  end
33
33
 
@@ -46,10 +46,15 @@ module Dry
46
46
  # @raise [NoMethodError] if there was no case called `name` given to
47
47
  # {#initialize} in `cases` hash
48
48
  def method_missing(name, *args, &block)
49
- return super unless @cases.key?(name)
49
+ kase = @cases.fetch(name) { return super }
50
50
 
51
51
  @unhandled_cases.delete name
52
- handle_case @cases[name], *args, &block
52
+
53
+ unless defined? @output
54
+ kase.(@result, args) do |result|
55
+ @output = yield(result)
56
+ end
57
+ end
53
58
  end
54
59
 
55
60
  private
@@ -59,17 +64,6 @@ module Dry
59
64
  ::Kernel.raise NonExhaustiveMatchError, "cases +#{@unhandled_cases.join(', ')}+ not handled"
60
65
  end
61
66
  end
62
-
63
- # @param [Case] kase
64
- # @param [Array] pattern
65
- def handle_case(kase, *pattern)
66
- return @output if @matched
67
-
68
- if kase.matches?(@result, *pattern)
69
- @matched = true
70
- @output = yield(kase.resolve(@result))
71
- end
72
- end
73
67
  end
74
68
  end
75
69
  end
@@ -1,7 +1,21 @@
1
- require "dry/matcher"
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/matcher'
2
4
 
3
5
  module Dry
4
6
  class Matcher
7
+ match = ::Proc.new do |value, patterns|
8
+ if patterns.empty?
9
+ value
10
+ elsif value.is_a?(::Array) && patterns.any? { |p| p === value[0] }
11
+ value
12
+ elsif patterns.any? { |p| p === value }
13
+ value
14
+ else
15
+ Undefined
16
+ end
17
+ end
18
+
5
19
  # Built-in {Matcher} ready to use with `Result` or `Try` monads from
6
20
  # [dry-monads](/gems/dry-monads) or any other compatible gems.
7
21
  #
@@ -16,7 +30,7 @@ module Dry
16
30
  # @return [Dry::Matcher]
17
31
  #
18
32
  # @example Usage with `dry-monads`
19
- # require 'dry-monads'
33
+ # require 'dry/monads/result'
20
34
  # require 'dry/matcher/result_matcher'
21
35
  #
22
36
  # value = Dry::Monads::Result::Success.new('success!')
@@ -48,27 +62,43 @@ module Dry
48
62
  # m.success { |v| "#{v.inspect} is truthy" }
49
63
  # m.failure { |v| "#{v.inspect} is falsey" }
50
64
  # end # => "nil is falsey"
65
+ #
66
+ # @example Usage with error codes
67
+ # value = Dry::Monads::Result::Failure.new([:invalid, :reasons])
68
+ #
69
+ # Dry::Matcher::ResultMatcher.(value) do |m|
70
+ # m.success do |v|
71
+ # "Yay: #{v}"
72
+ # end
73
+ #
74
+ # m.failure(:not_found) do
75
+ # "No such thing"
76
+ # end
77
+ #
78
+ # m.failure(:invalid) do |_code, errors|
79
+ # "Cannot be done: #{errors.inspect}"
80
+ # end
81
+ # end #=> "Cannot be done: :reasons"
82
+ #
51
83
  ResultMatcher = Dry::Matcher.new(
52
- success: Case.new(
53
- match: -> result, *pattern {
54
- result = result.to_result
55
- result.success?
56
- },
57
- resolve: -> result {
58
- result = result.to_result
59
- result.value!
60
- },
61
- ),
62
- failure: Case.new(
63
- match: -> result, *pattern {
64
- result = result.to_result
65
- result.failure?
66
- },
67
- resolve: -> result {
68
- result = result.to_result
69
- result.failure
70
- },
71
- )
84
+ success: Case.new { |result, patterns|
85
+ result = result.to_result
86
+
87
+ if result.success?
88
+ match.(result.value!, patterns)
89
+ else
90
+ Undefined
91
+ end
92
+ },
93
+ failure: Case.new { |result, patterns|
94
+ result = result.to_result
95
+
96
+ if result.failure?
97
+ match.(result.failure, patterns)
98
+ else
99
+ Undefined
100
+ end
101
+ }
72
102
  )
73
103
  end
74
104
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dry
2
4
  class Matcher
3
- VERSION = "0.7.0".freeze
5
+ VERSION = '0.8.0'
4
6
  end
5
7
  end
metadata CHANGED
@@ -1,97 +1,49 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-matcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Riley
8
+ - Nikita Shilnikov
8
9
  autorequire:
9
- bindir: bin
10
+ bindir: exe
10
11
  cert_chain: []
11
- date: 2018-01-10 00:00:00.000000000 Z
12
+ date: 2019-07-30 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.10'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.10'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: 10.4.2
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: 10.4.2
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 3.3.0
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 3.3.0
55
- - !ruby/object:Gem::Dependency
56
- name: simplecov
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 0.10.0
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 0.10.0
69
- - !ruby/object:Gem::Dependency
70
- name: yard
15
+ name: dry-core
71
16
  requirement: !ruby/object:Gem::Requirement
72
17
  requirements:
73
18
  - - ">="
74
19
  - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
20
+ version: 0.4.7
21
+ type: :runtime
77
22
  prerelease: false
78
23
  version_requirements: !ruby/object:Gem::Requirement
79
24
  requirements:
80
25
  - - ">="
81
26
  - !ruby/object:Gem::Version
82
- version: '0'
27
+ version: 0.4.7
83
28
  description: Flexible, expressive pattern matching for Ruby
84
29
  email:
85
30
  - tim@icelab.com.au
31
+ - fg@flashgordon.ru
86
32
  executables: []
87
33
  extensions: []
88
34
  extra_rdoc_files: []
89
35
  files:
36
+ - ".codeclimate.yml"
37
+ - ".gitignore"
38
+ - ".rspec"
39
+ - ".travis.yml"
40
+ - ".yardopts"
90
41
  - CHANGELOG.md
91
42
  - Gemfile
92
43
  - LICENSE.md
93
44
  - README.md
94
45
  - Rakefile
46
+ - dry-matcher.gemspec
95
47
  - lib/dry-matcher.rb
96
48
  - lib/dry/matcher.rb
97
49
  - lib/dry/matcher/case.rb
@@ -99,12 +51,6 @@ files:
99
51
  - lib/dry/matcher/evaluator.rb
100
52
  - lib/dry/matcher/result_matcher.rb
101
53
  - lib/dry/matcher/version.rb
102
- - spec/examples.txt
103
- - spec/integration/class_enhancement_spec.rb
104
- - spec/integration/matcher_spec.rb
105
- - spec/integration/result_matcher_spec.rb
106
- - spec/spec_helper.rb
107
- - spec/unit/case_spec.rb
108
54
  homepage: http://dry-rb.org/gems/dry-matcher
109
55
  licenses:
110
56
  - MIT
@@ -117,15 +63,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
63
  requirements:
118
64
  - - ">="
119
65
  - !ruby/object:Gem::Version
120
- version: 2.2.0
66
+ version: 2.4.0
121
67
  required_rubygems_version: !ruby/object:Gem::Requirement
122
68
  requirements:
123
69
  - - ">="
124
70
  - !ruby/object:Gem::Version
125
71
  version: '0'
126
72
  requirements: []
127
- rubyforge_project:
128
- rubygems_version: 2.7.3
73
+ rubygems_version: 3.0.3
129
74
  signing_key:
130
75
  specification_version: 4
131
76
  summary: Flexible, expressive pattern matching for Ruby
@@ -1,18 +0,0 @@
1
- example_id | status | run_time |
2
- ----------------------------------------------------- | ------ | --------------- |
3
- ./spec/integration/class_enhancement_spec.rb[1:1:1:1] | passed | 0.00011 seconds |
4
- ./spec/integration/class_enhancement_spec.rb[1:1:2:1] | passed | 0.0001 seconds |
5
- ./spec/integration/class_enhancement_spec.rb[1:2:1:1] | passed | 0.00014 seconds |
6
- ./spec/integration/class_enhancement_spec.rb[1:2:2:1] | passed | 0.0001 seconds |
7
- ./spec/integration/matcher_spec.rb[1:1:1] | passed | 0.00017 seconds |
8
- ./spec/integration/matcher_spec.rb[1:1:2] | passed | 0.0001 seconds |
9
- ./spec/integration/matcher_spec.rb[1:1:3] | passed | 0.00122 seconds |
10
- ./spec/integration/matcher_spec.rb[1:1:4:1] | passed | 0.00009 seconds |
11
- ./spec/integration/matcher_spec.rb[1:1:4:2] | passed | 0.00147 seconds |
12
- ./spec/integration/result_matcher_spec.rb[1:1:1:1] | passed | 0.00012 seconds |
13
- ./spec/integration/result_matcher_spec.rb[1:1:2:1] | passed | 0.00008 seconds |
14
- ./spec/integration/result_matcher_spec.rb[1:1:3:1:1] | passed | 0.00015 seconds |
15
- ./spec/integration/result_matcher_spec.rb[1:1:3:2:1] | passed | 0.00017 seconds |
16
- ./spec/unit/case_spec.rb[1:1:1] | passed | 0.00087 seconds |
17
- ./spec/unit/case_spec.rb[1:2:1] | passed | 0.00008 seconds |
18
- ./spec/unit/case_spec.rb[1:2:2] | passed | 0.00056 seconds |
@@ -1,64 +0,0 @@
1
- require "dry-monads"
2
- require "dry/matcher/result_matcher"
3
-
4
- RSpec.describe "Class enhancement with Dry::Matcher.for" do
5
- let(:operation) {
6
- Class.new do
7
- include Dry::Matcher.for(:call, with: Dry::Matcher::ResultMatcher)
8
-
9
- def call(bool)
10
- bool ? Dry::Monads::Success("a success") : Dry::Monads::Failure("a failure")
11
- end
12
- end.new
13
- }
14
-
15
- describe "match blocks" do
16
- subject(:match) {
17
- operation.call(input) do |m|
18
- m.success do |v|
19
- "Matched success: #{v}"
20
- end
21
-
22
- m.failure do |v|
23
- "Matched failure: #{v}"
24
- end
25
- end
26
- }
27
-
28
- context "successful result" do
29
- let(:input) { true }
30
-
31
- it "matches on success" do
32
- expect(match).to eq "Matched success: a success"
33
- end
34
- end
35
-
36
- context "failed result" do
37
- let(:input) { false }
38
-
39
- it "matches on failure" do
40
- expect(match).to eq "Matched failure: a failure"
41
- end
42
- end
43
- end
44
-
45
- describe "without match blocks" do
46
- subject(:result) { operation.call(input) }
47
-
48
- context "successful result" do
49
- let(:input) { true }
50
-
51
- it "returns the result" do
52
- expect(result).to eq Dry::Monads::Success("a success")
53
- end
54
- end
55
-
56
- context "failed result" do
57
- let(:input) { false }
58
-
59
- it "returns the result" do
60
- expect(result).to eq Dry::Monads::Failure("a failure")
61
- end
62
- end
63
- end
64
- end
@@ -1,96 +0,0 @@
1
- require "dry-monads"
2
-
3
- RSpec.describe Dry::Matcher do
4
- context "with match cases provided" do
5
- let(:success_case) {
6
- Dry::Matcher::Case.new(
7
- match: -> result { result.success? },
8
- resolve: -> result { result.value! },
9
- )
10
- }
11
-
12
- let(:failure_case) {
13
- Dry::Matcher::Case.new(
14
- match: -> result { result.failure? },
15
- resolve: -> result { result.failure },
16
- )
17
- }
18
-
19
- let(:matcher) {
20
- Dry::Matcher.new(
21
- success: success_case,
22
- failure: failure_case,
23
- )
24
- }
25
-
26
- def call_match(input)
27
- matcher.(input) do |m|
28
- m.success do |v|
29
- "Success: #{v}"
30
- end
31
-
32
- m.failure do |v|
33
- "Failure: #{v}"
34
- end
35
- end
36
- end
37
-
38
- it "matches on success" do
39
- input = Dry::Monads::Success("Yes!")
40
- expect(call_match(input)).to eq "Success: Yes!"
41
- end
42
-
43
- it "matches on failure" do
44
- input = Dry::Monads::Failure("No!")
45
- expect(call_match(input)).to eq "Failure: No!"
46
- end
47
-
48
- it "requires an exhaustive match" do
49
- input = Dry::Monads::Success("Yes!")
50
-
51
- expect {
52
- matcher.(input) do |m|
53
- m.success { |v| "Success: #{v}" }
54
- end
55
- }.to raise_error Dry::Matcher::NonExhaustiveMatchError
56
- end
57
-
58
- context "with patterns" do
59
- let(:success_case) {
60
- Dry::Matcher::Case.new(
61
- match: -> result { result.first == :ok },
62
- resolve: -> result { result.last },
63
- )
64
- }
65
-
66
- let(:failure_case) {
67
- Dry::Matcher::Case.new(
68
- match: -> result, failure_type {
69
- result.length == 3 && result[0] == :failure && result[1] == failure_type
70
- },
71
- resolve: -> result { result.last },
72
- )
73
- }
74
-
75
- def call_match(input)
76
- matcher.(input) do |m|
77
- m.success
78
-
79
- m.failure :my_error do |v|
80
- "Pattern-matched failure: #{v}"
81
- end
82
- end
83
- end
84
-
85
- it "matches using the provided pattern" do
86
- input = [:failure, :my_error, "No!"]
87
- expect(call_match(input)).to eq "Pattern-matched failure: No!"
88
- end
89
-
90
- it "doesn't match if the pattern doesn't match" do
91
- input = [:failure, :non_matching_error, "No!"]
92
- expect(call_match(input)).to be_nil
93
- end
94
- end
95
- end
96
- end
@@ -1,56 +0,0 @@
1
- require "dry-monads"
2
- require "dry/matcher/result_matcher"
3
-
4
- RSpec.describe "Dry::Matcher::ResultMatcher" do
5
- describe "external matching" do
6
- subject(:match) {
7
- Dry::Matcher::ResultMatcher.(result) do |m|
8
- m.success do |v|
9
- "Matched success: #{v}"
10
- end
11
-
12
- m.failure do |v|
13
- "Matched failure: #{v}"
14
- end
15
- end
16
- }
17
-
18
- context "successful result" do
19
- let(:result) { Dry::Monads::Success("a success") }
20
-
21
- it "matches on success" do
22
- expect(match).to eq "Matched success: a success"
23
- end
24
- end
25
-
26
- context "failed result" do
27
- let(:result) { Dry::Monads::Failure("a failure") }
28
-
29
- it "matches on failure" do
30
- expect(match).to eq "Matched failure: a failure"
31
- end
32
- end
33
-
34
- context "result convertible to result" do
35
- context "converts to success" do
36
- let(:result) {
37
- Dry::Monads::Try.lift([StandardError], -> { 'a success' })
38
- }
39
-
40
- it "matches on success" do
41
- expect(match).to eq "Matched success: a success"
42
- end
43
- end
44
-
45
- context "converts to failure" do
46
- let(:result) {
47
- Dry::Monads::Try.lift([StandardError], -> { raise('a failure') })
48
- }
49
-
50
- it "matches on failure" do
51
- expect(match).to eq "Matched failure: a failure"
52
- end
53
- end
54
- end
55
- end
56
- end
@@ -1,57 +0,0 @@
1
- if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.3"
2
- require "simplecov"
3
- SimpleCov.start
4
- end
5
-
6
-
7
- begin
8
- require "byebug"
9
- rescue LoadError; end
10
-
11
- require "dry-matcher"
12
-
13
- Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each do |f| require f end
14
-
15
- RSpec.configure do |config|
16
- config.disable_monkey_patching!
17
-
18
- config.expect_with :rspec do |expectations|
19
- # This option will default to `true` in RSpec 4.
20
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
21
- end
22
-
23
- config.mock_with :rspec do |mocks|
24
- # This option will default to `true` in RSpec 4.
25
- mocks.verify_partial_doubles = true
26
- end
27
-
28
- # Allows RSpec to persist some state between runs in order to support
29
- # the `--only-failures` and `--next-failure` CLI options. We recommend
30
- # you configure your source control system to ignore this file.
31
- config.example_status_persistence_file_path = "spec/examples.txt"
32
-
33
- # This setting enables warnings. It's recommended, but in some cases may
34
- # be too noisy due to issues in dependencies.
35
- config.warnings = true
36
-
37
- # Many RSpec users commonly either run the entire suite or an individual
38
- # file, and it's useful to allow more verbose output when running an
39
- # individual spec file.
40
- if config.files_to_run.one?
41
- # Use the documentation formatter for detailed output, unless a formatter
42
- # has already been configured (e.g. via a command-line flag).
43
- config.default_formatter = "doc"
44
- end
45
-
46
- # Run specs in random order to surface order dependencies. If you find an
47
- # order dependency and want to debug it, you can fix the order by providing
48
- # the seed, which is printed after each run.
49
- # --seed 1234
50
- config.order = :random
51
-
52
- # Seed global randomization in this process using the `--seed` CLI option.
53
- # Setting this allows you to use `--seed` to deterministically reproduce
54
- # test failures related to randomization by passing the same `--seed` value
55
- # as the one that triggered the failure.
56
- Kernel.srand config.seed
57
- end
@@ -1,22 +0,0 @@
1
- RSpec.describe Dry::Matcher::Case do
2
- describe "#matches?" do
3
- it "calls the match proc with the value" do
4
- kase = described_class.new(match: -> value { value.even? })
5
- expect(kase.matches?(2)).to be true
6
- expect(kase.matches?(1)).to be false
7
- end
8
- end
9
-
10
- describe "#resolve" do
11
- it "calls the resolve proc with the value" do
12
- kase = described_class.new(match: -> * { true }, resolve: -> value { value.to_s })
13
-
14
- expect(kase.resolve(123)).to eq "123"
15
- end
16
-
17
- it "defaults to passing through the value" do
18
- kase = described_class.new(match: -> * { true })
19
- expect(kase.resolve(123)).to eq 123
20
- end
21
- end
22
- end