Created
October 10, 2011 01:43
-
-
Save forforf/1274459 to your computer and use it in GitHub Desktop.
NEO-Refactoring 2
This file contains 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
module NeoMethods | |
#include NeoProxy | |
#ThinProxy objects must be used when the object doesn't support #define_singleton_method (i.e. symbols) | |
#SymbolMethods = {:sym_add => lambda{|x| result = (self.to_s + x.to_s).to_sym; replace_self(result)} } | |
module Symbol | |
Methods = { | |
:sym_add => lambda do |x| | |
#proxy = ThinProxy.new(self) | |
sum = self.to_s + x.to_s | |
sum = sum.to_sym | |
replace_self(sum) | |
end | |
} | |
end | |
module Num | |
Methods = { | |
:num_add => lambda do |x| | |
puts "num self: #{self.inspect}" | |
sum = self.to_f + x.to_f | |
replace_self(sum) | |
end | |
} | |
end | |
end | |
module DataOps | |
include NeoMethods | |
Def = { | |
:syms => Symbol::Methods, | |
:nums => Num::Methods | |
} | |
end | |
module NeoProxy | |
include DataOps | |
class ThinProxy < BasicObject | |
attr_accessor :obj | |
def initialize(obj) | |
@obj = obj | |
end | |
def define_method(method_name, callable=nil, &block) | |
block ||= callable | |
metaclass = class << self; self; end | |
metaclass.send(:define_method, method_name, block) | |
end | |
def replace_self(new_obj) | |
@obj = new_obj | |
end | |
def method_missing(method, *args, &block) | |
obj.send(method, *args, &block) | |
end | |
end | |
def set_neo_methods(key, val=nil) | |
neo_hsh = {} | |
puts "setting neo meth: #{key.inspect}: #{val.inspect}" | |
#proxy_key = ThinProxy.new(key) | |
proxy_val = ThinProxy.new(val) | |
#proxy_key.define_method(proxy_key.to_sym, lambda{proxy_val}) | |
#proxy_key.define_method(:[]=, new_value, proxy_key.replace_self | |
neo_methods = Def[key] #method_name => lambda, etc | |
neo_methods.each do |method_name, block| | |
proxy_val.define_method(method_name, block) | |
end | |
#neo_hsh[proxy_key] = proxy_val | |
neo_hsh[key] = proxy_val | |
neo_hsh | |
end | |
end | |
class TkSymBase | |
include NeoProxy | |
class << self; attr_accessor :data_ops, end | |
self.data_ops = nil #to be set by base classes | |
def initialize(hsh_orig = {}) | |
plain_hsh = hsh_orig.dup | |
proxy_hsh = {} | |
plain_hsh.each do |k,v| | |
#proxy_obj = ThinProxy.new(v) | |
#self.class.__send__(:define_method, "#{k}".to_sym, lambda {hsh[k]} ) | |
#self.class.__send__(:define_method, "#{k}=".to_sym, lambda {|new_val| hsh[k] = proxy_obj} ) | |
#obj_methods.each do |method_name, block| | |
# proxy_obj.define_singleton_method(method_name, block) | |
# #backwards compatibility to tinkit | |
# #also a way to avoid chaining send methods when calling the method dynamically | |
# tk_meth_name = "#{k}_#{method_name}".to_sym | |
# #define a method on self that calls the proxy_obj method just defined | |
# self.define_singleton_method(tk_meth_name, lambda{|x| proxy_obj.__send__(method_name, x)}) | |
#end | |
#self.class.data_ops.each do |key, ops| | |
#end | |
neo_data = set_neo_methods(k,v) | |
proxy_hsh.merge!(neo_data) | |
p proxy_hsh.values.first.sym_add(:foo) | |
p proxy_hsh[k].sym_add(:bar) | |
end | |
proxy_hsh.each do |k, proxy_v| | |
self.class.__send__(:define_method, k.to_sym, lambda{proxy_hsh[k]}) | |
puts "test" | |
p k | |
p self.__send__ k.to_sym | |
end | |
end | |
def add_data(hsh) | |
new_hsh = {} | |
hsh.each do |k,v| | |
neo_data = set_neo_methods(k,v) | |
new_hsh.merge!(neo_data) | |
end | |
new_hsh.each do |k, proxy_v| | |
self.class.__send__(:define_method, k.to_sym, lambda{new_hsh[k]}) | |
end | |
end | |
end | |
module TkSymFactory | |
#include TkSyms | |
def self.make(data_ops_def) | |
#tkClass = TkSyms.const_set(className.to_sym, TkSymBase) | |
tkClass = Class.new(TkSymBase) | |
data_ops_def.each do |key, ops| | |
tkClass.data_ops = data_ops_def | |
#ops.instance_methods.each do |inst_meth| | |
end | |
tkClass | |
end | |
end | |
MyTkClass = TkSymFactory.make(DataOps::Def) | |
p MyTkClass | |
p MyTkClass.instance_methods | |
h = {:syms => :a} | |
x = MyTkClass.new(h) | |
p x | |
p x.syms | |
#p x.syms.instance_methods | |
p x.syms.sym_add(:b) | |
x.add_data(:nums => 1) | |
p x | |
p x.nums | |
p x.nums.num_add(4) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment