-
-
Save duckinator/bad02061c7d0e65192f9 to your computer and use it in GitHub Desktop.
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 Variant | |
attr_accessor :variant_tag | |
def self.variants(hsh) | |
hsh.map do |tag, args| | |
variant(tag, args) | |
end | |
end | |
def self.variant(tag, args) | |
args = [args] unless args.is_a?(Array) | |
@@variants ||= {} | |
@@variants[tag] = args | |
arg_definitions = @@variants[tag].map do |arg_name| | |
"tmp.#{arg_name} = %s" | |
end.join("\n ") | |
code = <<-EOF | |
def #{tag.to_s}(#{args.join(', ')}) | |
attr_accessor *#{args.inspect} | |
tag = #{tag.inspect} | |
tmp = self.new | |
tmp.variant_tag = tag | |
#{format(arg_definitions, *args)} | |
tmp | |
end | |
EOF | |
self.class.class_eval code | |
tag | |
end | |
def cases(hsh) | |
hsh.each do |k, v| | |
if variant_tag == k | |
args = @@variants[k].map{|x| send(x)} | |
return v.call(*args) | |
end | |
end | |
end | |
end | |
class Order < Variant | |
variants delivery: [:address], | |
digital: [:email], | |
pickup: [:store_id] | |
end | |
def test(order) | |
puts order.cases( | |
delivery: ->(address) { "delivering to #{address}" }, | |
digital: ->(email) { "emailing to #{email}" }, | |
pickup: ->(store_id) { | |
"picking up from store ##{store_id}" | |
}, | |
) | |
end | |
# n constructors | |
test Order.delivery('123 Main St') #=> delivering to 123 Main St | |
test Order.digital('[email protected]') #=> emailing to [email protected] | |
test Order.pickup(456) #=> picking up from store #456 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment