From: ara.t.howard@... Date: 2006-02-06T01:31:27+09:00 Subject: Re: define_method with a &block? On Sun, 5 Feb 2006, Erik Veenstra wrote: > One way to overcome this, without putting the whole method in one big > string, is using a temporary method, like this: > > method_name = "test2" > module_eval do > def temp_method(*args, &block) > p [method_name, args, block_given?] > end > eval("alias :#{method_name} :temp_method") > undef :temp_method > end > > See code below, Test#test4. > > Comments? Suggestions? i'm having a hard time imagining a case where only the name of the method would need to be added and not the body - doesn't really seem like meta-programming - for instance the method above generates something which will always use 'method_name' as 'test2'. - if this string is known when you're editing then you don't need meta-programming at all. - if it is not known, but the method body is, then you don't need to go though such lengths to factor out variables and avoid strings - only to eval a string eval("alias :#{method_name} :temp_method") you could have simply put your entire method def in this eval of a string! ;-) of course maybe you could use alias_method method_name, "temp_method" to avoid that eval... - lastly, if both the method body and name cannot be totally know until runtime and you really, really want to avoid just having a simple method that generates a string def of the method and would like to factor out the state and behaviour of that method why not objectify it? harp:~ > cat a.rb require "forwardable" class Test extend Forwardable def test1(*args, &block) p [:test1, args, block_given?] end # abstract all state and behaviour for method here class TestMethod attr "name" attr "data" def initialize(name, data) @name, @data = name, data end def call(*a, &b) p [@name, @data, a, !b.nil?] end end METHODS = {} def Test::add_test_method name name = name.to_s METHODS[name] = TestMethod::new name, 42 accessor = "__#{ name }__" define_method(accessor){ METHODS[name] } def_delegator accessor, "call", name end end Test.new.test1(1, 2, 3){} Test::add_test_method "test2" Test.new.test2(1, 2, 3){} harp:~ > ruby a.rb [:test1, [1, 2, 3], true] ["test2", 42, [1, 2, 3], true] sure would be easier ruby had some way to declare blocks that take blocks! ;-) regards. -a -- happiness is not something ready-made. it comes from your own actions. - h.h. the 14th dali lama