From: Pat Maddox Date: 2006-08-07T10:21:16+09:00 Subject: Re: Singleton methods with method_missing On Monday, August 07, 2006, at 4:08 AM, Sander Land wrote: >On 8/6/06, Pat Maddox wrote: >> I don't have any practical use for this, but I was experimenting a bit. >> I just want to create singleton methods on objects of this class. >> There's more to come, but this is the part I'm stuck at :) >> >> This code doesn't actually work, but I think it's close (I hope?) >> >> When I do this I get "NameError: undefined local variable or method `m' >> for #>" so I think it means that m just isn't >> in scope for the singleton class. How can I define the singleton >> method? Is there any way to use binding here? > >It is close :) >class<defined there. A solution is to use blocks for everything, using *eval >functions. > >class OneShot > def method_missing(m,*a) > puts "method #{m} missing!" > (class< define_method(m) { puts m.to_s } > } > send(m) > end >end > >a = OneShot.new >a.foo >a.foo >b = OneShot.new >b.foo >b.foo > >output: >method foo missing! >foo >foo >method foo missing! >foo >foo > >Which is what you want, right? > Okay yeah, that works great. Why do you use class_eval there? fwiw, I tried it with instance_eval and got the same behavior. I still don't really understand the difference. Alright, so now that that's out of the way, I want to be able to undefine methods. I also want to keep track of any that get undefined so that they can't be redefined at all: class OneShot def initialize @methods = [] end def method_missing(m, *args, &block) puts @methods.inspect raise "Sorry bud, you already had your shot" if @methods.include?(m) puts "Defining #{m}" (class << self; self; end).class_eval { define_method(m) { puts m.to_s } } send(m) end private def remove_method(m) @methods << m (class << self; self; end).class_eval { remove_method(m) } end end If I make remove_method public, I can just call o.remove_method(:foo) and it works as expected. Apparently remove_method is a private method though, so I was wondering if I could keep it that way. The code I saw in Ruby Cookbook showed something like class << o remove_method :foo end That doesn't actually call my custom remove_method though. If I understand correctly, it's because that syntax is actually calling remove_method on the singleton class. Other than making remove_method public, I'm not sure how to do what I want. Pat -- Posted with http://DevLists.com. Sign up and save your mailbox.