Skip to content

Commit 66a5ca2

Browse files
authored
Merge pull request #111 from dry-rb/add-deconstruct-keys
Add support for deconstruct_keys
2 parents 1948979 + 8c9ab03 commit 66a5ca2

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

lib/dry/monads/right_biased.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ def and(mb)
191191
# in Success(2..100) then ...
192192
# in Success(2..200 => code) then ...
193193
# end
194+
#
194195
# @api private
195196
def deconstruct
196197
if Unit.equal?(@value)
@@ -202,6 +203,25 @@ def deconstruct
202203
end
203204
end
204205

206+
# Pattern matching hash values
207+
#
208+
# @example
209+
# case Success(x)
210+
# in Success(code: 200...300) then :ok
211+
# in Success(code: 300...400) then :redirect
212+
# in Success(code: 400...500) then :user_error
213+
# in Success(code: 500...600) then :server_error
214+
# end
215+
#
216+
# @api private
217+
def deconstruct_keys(_)
218+
if @value.is_a?(::Hash)
219+
@value
220+
else
221+
EMPTY_HASH
222+
end
223+
end
224+
205225
private
206226

207227
# @api private
@@ -340,6 +360,23 @@ def deconstruct
340360
[@value]
341361
end
342362
end
363+
364+
# Pattern matching hash values
365+
#
366+
# @example
367+
# case Failure(x)
368+
# in Failure(code: 400...500) then :user_error
369+
# in Failure(code: 500...600) then :server_error
370+
# end
371+
#
372+
# @api private
373+
def deconstruct_keys(_)
374+
if @value.is_a?(::Hash)
375+
@value
376+
else
377+
EMPTY_HASH
378+
end
379+
end
343380
end
344381
end
345382
end

spec/integration/pattern_matching_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def call(value)
1919
in Success(:code, x) then x
2020
in Success[:status, x] then x
2121
in Success({ status: x }) then x
22+
in Success(code: 301 | 302) then :redirect
2223
in Success({ code: 200..300 => x }) then x
2324
end
2425
end
@@ -32,6 +33,10 @@ def call(value)
3233
expect(match.(Success([:status, 600]))).to eql(600)
3334
expect(match.(Success({ status: 404 }))).to eql(404)
3435
expect(match.(Success({ code: 204 }))).to eql(204)
36+
expect(match.(Success(code: 301))).to eql(:redirect)
37+
expect(match.(Success(code: 302))).to eql(:redirect)
38+
expect { match.(Success(code: 303)) }.to raise_error(NoMatchingPatternError)
39+
expect { match.(Success([:foo])) }.to raise_error(NoMatchingPatternError)
3540
end
3641
end
3742

@@ -46,6 +51,7 @@ def call(value)
4651
case value
4752
in Failure[:not_found, reason] then reason
4853
in Failure(:error) then :nope
54+
in Failure(error: code) then code
4955
in Failure() then :unit
5056
end
5157
end
@@ -54,6 +60,7 @@ def call(value)
5460
expect(match.(Failure([:not_found, :no]))).to eql(:no)
5561
expect(match.(Failure(:error))).to eql(:nope)
5662
expect(match.(Failure())).to eql(:unit)
63+
expect(match.(Failure(error: :bug))).to eql(:bug)
5764
expect { match.(Failure(3)) }.to raise_error(NoMatchingPatternError)
5865
end
5966
end

0 commit comments

Comments
 (0)