Skip to content

Instantly share code, notes, and snippets.

@elskwid
Created May 21, 2013 22:32
Show Gist options
  • Save elskwid/5623804 to your computer and use it in GitHub Desktop.
Save elskwid/5623804 to your computer and use it in GitHub Desktop.
Playing with modules and bindings
class Configuration
attr_reader :name
def initialize(name)
@name = name
end
end
class ModuleBuilder
def self.call(name)
configuration = Configuration.new(name)
Module.new.tap do |mod|
included_method(mod, configuration)
string_instance_method(mod, configuration)
proc_instance_method(mod, configuration)
end
end
def self.included_method(mod, config)
mod.module_eval do
# Using nested procs
# meth = ->(object) do
# puts ">> config: #{config}"
# puts ">> #{self.name} included in #{object.name}"
#
# # define overide class method
# override_meth = ->() do
# puts ">> cm config: #{config}"
# puts ">> class method defined in #{self.name}"
# end
# object.send :define_singleton_method, :cm, override_meth
# end
#
# self.send :define_singleton_method, :included, meth
# Since we're in the module we can use define_singleton_method directly
define_singleton_method :included do |object|
puts ">> config: #{config}"
puts ">> #{self.name} included in #{object.name}"
# define overide class method
override_meth = ->() do
puts ">> cm config: #{config}"
puts ">> class method defined in #{self.name}"
end
object.send :define_singleton_method, :cm, override_meth
end
end
end
def self.string_instance_method(mod, config)
mod.module_eval(%Q{
def im_string
puts ">> instance method defined with string eval in Module #{config.name}"
end
})
end
def self.proc_instance_method(mod, config)
mod.module_eval do
meth = ->() { puts ">> instance method defined with proc in Module #{config.name}" }
self.send :define_method, :im_proc, meth
end
end
end
FooModule = ModuleBuilder.call(:foo)
BarModule = ModuleBuilder.call(:bar)
class A
def self.cm
puts ">> class method defined on A"
end
def im
puts ">> instance method defined in Class A"
end
end
class B < A
include FooModule
end
class C < A
include BarModule
end
# >> config: #<Configuration:0x007f88040206a0>
# >> FooModule included in B
# >> config: #<Configuration:0x007f880401bbc8>
# >> BarModule included in C
A.cm
# >> class method defined on A
A.new.im
# >> instance method defined in Class A
B.cm
# >> cm config: #<Configuration:0x007f88040206a0>
# >> class method defined in B
B.new.im
# >> instance method defined in Class A
B.new.im_string
# >> instance method defined with string eval in Module foo
B.new.im_proc
# >> instance method defined with proc in Module foo
C.cm
# >> cm config: #<Configuration:0x007f880401bbc8>
# >> class method defined in C
C.new.im
# >> instance method defined in Class A
C.new.im_string
# >> instance method defined with string eval in Module bar
C.new.im_proc
# >> instance method defined with proc in Module bar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment