From: "John-Mason P. Shackelford" Date: 2005-03-31T06:05:48+09:00 Subject: changing the context in which a block executes Greetings. I'd like to define a method which accepts a block such callers can write: some_method do op1(arg) op2(arg) end instead of: some_method do |obj| obj.op1(arg) obj.op2(arg) end Since within a block self.class.name always returns Object (not the object of the method which takes the block) it is necessary to use instance_eval to expose methods available within the context of the block. This however, breaks encapsulation exposing an object's instance data and private methods to the block. One approach to preventing the leak of private fields and methods to the block would be to use an adaptor which only routes selected calls to the class which defines methods for the block's use. The code below demonstrates this approach. My question is, is this the best way to achieve this in Ruby? Thanks, John-Mason Shackelford Software Developer Pearson Educational Measurement 2510 North Dodge St. Iowa City, IA 52245 ph. 319-354-9200x6214 john-mason.shackelford@pearson.com http://www.pearson.com/ -- code --- class MacroExec def self.with(klass, &block) lang = klass.new safe_lang = SafetyAdaptor.new(lang) safe_lang.instance_eval(&block) end end class SafetyAdaptor def initialize(lang_def) @macro_lang = lang_def end def method_missing(m, *args) if legal_methods.include?(m.to_s) @macro_lang.class.instance_method(m).bind(@macro_lang).call(*args) else @macro_lang.method_missing(m, *args) end end private def legal_methods @macro_lang.public_methods() end end class MacroLang def initialize; @private_data = true end def hello_world; puts 'Hello World' end def method_missing(m, *args) puts "Undefined term #{m}." end private def private_message puts 'Private!' end end MacroExec.with(MacroLang) do hello_world nosuch puts @private_data private_message end