Created
May 21, 2013 22:32
-
-
Save elskwid/5623804 to your computer and use it in GitHub Desktop.
Playing with modules and bindings
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 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