[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Singleton methods with method_missing

Stefan Lang

8/6/2006 6:17:00 PM

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?)

class OneShot
def method_missing(m)
class << self
define_method(m) { puts m.to_s }
end
send(m)
end
end

When I do this I get "NameError: undefined local variable or method `m'
for #<Class:#<OneShot:0x32cf74>>" 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?

Pat
--
Posted with http://De.... Sign up and save your mailbox.

4 Answers

Ezra Zygmuntowicz

8/6/2006 6:30:00 PM

0


On Aug 6, 2006, at 11:16 AM, 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?)
>
> class OneShot
> def method_missing(m)
def self.method_missing(m)
> class << self
> define_method(m) { puts m.to_s }
> end
> send(m)
> end
> end
>
> When I do this I get "NameError: undefined local variable or method
> `m'
> for #<Class:#<OneShot:0x32cf74>>" 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?
>
> Pat
> --
> Posted with http://De.... Sign up and save your mailbox.
>


That works unless I misunderstand your question.

-Ezra

dblack

8/6/2006 7:02:00 PM

0

Sander Land

8/6/2006 7:09:00 PM

0

On 8/6/06, Pat Maddox <devlists-ruby-talk@devlists.com> 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 #<Class:#<OneShot:0x32cf74>>" 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<<self .... end is not a closure (only blocks are), so m is not
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<<self;self;end).class_eval {
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?

Stefan Lang

8/7/2006 1:21:00 AM

0


On Monday, August 07, 2006, at 4:08 AM, Sander Land wrote:
>On 8/6/06, Pat Maddox <devlists-ruby-talk@devlists.com> 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 #<Class:#<OneShot:0x32cf74>>" 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<<self .... end is not a closure (only blocks are), so m is not
>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<<self;self;end).class_eval {
> 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://De.... Sign up and save your mailbox.