Skip to content

Instantly share code, notes, and snippets.

@jemc
Last active December 31, 2015 07:49
Show Gist options
  • Save jemc/7956510 to your computer and use it in GitHub Desktop.
Save jemc/7956510 to your computer and use it in GitHub Desktop.
A type of module combining distinct from include/extend
module HappehTheory
module SingleCell
def gelatin
trait
end
private
def trait(*args)
"a flagellum"
end
end
module Fish
def pyramid
trait
end
private
def trait(*args)
"a spine"
end
end
module Amphibian
def lick
trait
end
private
def trait(*args)
"a tongue"
end
end
module Reptile
def punch
trait
end
private
def trait(*args)
"an arm"
end
end
module Insect
def peer
trait
end
private
def trait(*args)
"an eyeball"
end
end
module Bird
def dance
trait
end
private
def trait(*args)
"a foot"
end
end
module Mammal
def reproduce
trait
end
private
def trait(*args)
"a live birth"
end
end
class Human
def combine mod
singleton_class = (class << self; self; end)
@combined_module_context ||= {}
# Wrap public methods to set the context variable
mod.instance_methods.each do |sym|
singleton_class.send :define_method, sym do |*args, &block|
saved = @combined_module_context[Thread.current]
@combined_module_context[Thread.current] = mod
mod.instance_method(sym).bind(self).call(*args, &block)
.tap { @combined_module_context[Thread.current] = saved }
end
end
# Wrap private methods to call the right method based on context
mod.private_instance_methods.each do |sym|
singleton_class.send :define_method, sym do |*args, &block|
this_mod = @combined_module_context[Thread.current]
raise NoMethodError, "private method ##{sym}" unless this_mod
this_mod.instance_method(sym).bind(self).call(*args, &block)
end
end
end
def initialize *args
yield self
end
end
end
include HappehTheory
h = Human.new do |d|
d.combine SingleCell
d.combine Fish
d.combine Amphibian
d.combine Reptile
d.combine Insect
d.combine Bird
d.combine Mammal
end
require 'pry'
binding.pry
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment