Last active
March 30, 2023 12:36
-
-
Save serradura/8d78880f0aef8924d3242824bc4c9917 to your computer and use it in GitHub Desktop.
NanoCase: Abstraction inspired by the u-case gem (compatible with old and new Rubies)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class NanoCase | |
class Result | |
UNDEFINED = :undefined | |
attr_reader :type, :data | |
def initialize(type, data) | |
@type = type | |
@data = data | |
end | |
def success? | |
raise NotImplementedError | |
end | |
def failure? | |
!success? | |
end | |
def on_success(type = UNDEFINED, &block) | |
self.tap { block.call(data) if success? && self.type == type } | |
end | |
def on_failure(type = UNDEFINED, &block) | |
self.tap { block.call(data) if failure? && self.type == type } | |
end | |
def and_then(&block) | |
success? ? block.call(data) : self | |
end | |
end | |
class Success < Result | |
def success? | |
true | |
end | |
end | |
class Failure < Result | |
def success? | |
false | |
end | |
end | |
def self.call(**args) | |
result = new(**args).call | |
return result if result.is_a?(Result) | |
raise TypeError, "#{self.name}#call must return a Result" | |
end | |
def initialize(**) | |
raise NotImplementedError | |
end | |
def call | |
raise NotImplementedError | |
end | |
private | |
def Success(type = Result::UNDEFINED, data: nil) | |
Success.new(type, data).freeze | |
end | |
def Failure(type = Result::UNDEFINED, data: nil) | |
Failure.new(type, data).freeze | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CreateUser < NanoCase | |
attr_reader :name | |
def initialize(name:) | |
@name = name | |
end | |
def call | |
return Failure(data: 'name must be a String') unless name.is_a?(String) | |
Success data: {user: {name: name}} | |
end | |
end | |
# --- | |
puts CreateUser.call(name: nil).inspect | |
#<NanoCase::Failure:0x0062adb0 @type=:undefined, @data="name must be a String"> | |
CreateUser.call(name: nil).on_failure { |data| p data } | |
CreateUser.call(name: nil).on_success { raise 'Never will reach here' } | |
CreateUser.call(name: nil).on_failure(:different_type) { raise 'Never will reach here' } | |
# --- | |
puts CreateUser.call(name: 'Serra').inspect | |
#<NanoCase::Success:0x0062abb8 @type=:undefined, @data={:user=>{:name=>"Serra"}}> | |
CreateUser.call(name: 'Serra').on_success { |data| p data } | |
CreateUser.call(name: 'Serra').on_failure { raise 'Never will reach here' } | |
CreateUser.call(name: 'Serra').on_success(:different_type) { raise 'Never will reach here' } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CreateUser < NanoCase | |
attr_reader :name | |
def initialize(name:) | |
@name = name | |
end | |
def call | |
validate_name | |
.and_then { create_user } | |
end | |
private | |
def validate_name | |
name.is_a?(String) ? Success() : Failure(data: 'name must be a String') | |
end | |
def create_user | |
Success(data: {user: {name: name}}) | |
end | |
end | |
# --- | |
result1 = CreateUser.call(name: nil) | |
puts result1.inspect | |
#<NanoCase::Failure:0x00628ab8 @type=:undefined, @data="name must be a String"> | |
result1.on_failure { |data| p data } | |
# "name must be a String" | |
result1.on_success { raise 'Never will reach here' } | |
result1.on_failure(:different_type) { raise 'Never will reach here' } | |
# --- | |
result2 = CreateUser.call(name: 'Serradura') | |
puts result2.inspect | |
#<NanoCase::Success:0x006288d8 @type=:undefined, @data={:user=>{:name=>"Serradura"}}> | |
result2.on_success { |data| p data } | |
# {:user=>{:name=>"Serradura"}} | |
result2.on_failure { raise 'Never will reach here' } | |
result2.on_success(:different_type) { raise 'Never will reach here' } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment