Skip to content

Instantly share code, notes, and snippets.

@ismasan
Created February 11, 2020 15:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ismasan/0aa03ea7e44fa49305a639a93b3bd0ba to your computer and use it in GitHub Desktop.
Save ismasan/0aa03ea7e44fa49305a639a93b3bd0ba to your computer and use it in GitHub Desktop.
Playing with composable value coercion policies
Result = Struct.new('Result', :mode, :value) do
def pass
copy(:pass)
end
def halt
copy(:halt)
end
def copy(new_mode)
self.class.new(new_mode, value)
end
end
class CoerceInteger
def call(result, key, hash)
# return result.pass if result.value.nil?
Result.new(:resolve, result.value.to_i)
end
end
class Default
def initialize(default)
@default = default
end
def call(result, key, hash)
case result.mode
when :resolve
result.pass
when :pass
Result.new(:resolve, @default)
end
end
end
class Maybe
def initialize(policy, on_nil: :halt)
@policy = policy
@on_nil = on_nil
end
def call(result, key, hash)
if result.value.nil? || !hash.key?(key)
return result.copy(@on_nil)
end
@policy.call(result, key, hash)
end
end
class Multiply
def initialize(factor = 1)
@factor = factor
end
def call(result, key, hash)
return Result.new(:resolve, result.value * @factor) if result.value.is_a?(Integer)
result.pass
end
end
def resolve(pipeline, key, hash)
value = hash[key]
result = Result.new(:start, hash[key])
pipeline.each do |policy|
result = policy.call(result, key, hash)
case result.mode
when :resolve
value = result.value
when :pass
next
when :halt
value = result.value
break
end
end
value
end
# Example
#
policies = [
Maybe.new(
CoerceInteger.new,
on_nil: :pass
),
Multiply.new(2),
Default.new(10)
]
puts resolve(policies, :value, { value: '11' }).inspect
puts resolve(policies, :value, { value: nil }).inspect
puts resolve(policies, :value, { }).inspect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment