Skip to content

Instantly share code, notes, and snippets.

@RomanTurner
Last active February 1, 2024 16:14
Show Gist options
  • Save RomanTurner/1ed15b5e8474a215901393c936027f0b to your computer and use it in GitHub Desktop.
Save RomanTurner/1ed15b5e8474a215901393c936027f0b to your computer and use it in GitHub Desktop.
Ruby Pattern Matching
class Response
attr_reader :status, :data
def initialize(status, data)
@status = status
@data = data
end
def deconstruct
by_status
end
def deconstruct_keys(_keys)
by_status
end
private
def by_status(ok: nil, error: nil, not_found: nil)
case @status
when 200
ok || { ok: @data }
when 404
not_found || { error: "File not found" }
else
error || {error: @data }
end
end
end
data = { one: "two", three: "four" }
case Response.new(200, data)
in ok: result
puts "Success: #{result}"
in error: reason
puts "Error: #{reason}"
end
#=> "Success: { one: "two", three: "four" }"
case Response.new(403, "Something went wrong")
in ok: result
puts "Success: #{result}"
in error: reason
puts "Error: #{reason}"
end
# => "Error: Something went wrong"
case Response.new(404)
in ok: result
puts "Success: #{result}"
in error: reason
puts "Error: #{reason}"
end
# => "Error: File not found"
# Imagine that you get a custom class returned from an API
ApiCustomResponseClass =
Struct.new(:status, :body, :message, keyword_init: true) do
def success?
status == 200
end
end
# It probably does not have #deconstruct or #deconstruct_keys so this Response class acts as a helpful wrapper.
class Response
attr_reader :status, :data
def initialize(res)
@status = res.status
@data = res.success? ? res.body : res.message
end
def deconstruct
by_status
end
def deconstruct_keys(_keys)
by_status
end
private
def by_status(ok: nil, error: nil, not_found: nil)
case @status
when 200
{ ok: @data }
else
{ error: @data }
end
end
end
successful_response =
ApiCustomResponseClass.new(
{ status: 200, body: { one: "two", three: "four" } }
)
failed_response =
ApiCustomResponseClass.new({ status: 403, message: "Unauthorized" })
not_found_response =
ApiCustomResponseClass.new({ status: 404, message: "File Not Found" })
[successful_response, failed_response, not_found_response].each do |res|
case Response.new(res)
in ok: result
puts "Success: #{result}"
in error: reason
puts "Error: #{reason}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment