Singleton methods with method_missing

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 :slight_smile:

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://DevLists.com. Sign up and save your mailbox.

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 :slight_smile:

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://DevLists.com. Sign up and save your mailbox.

That works unless I misunderstand your question.

-Ezra

路路路

On Aug 6, 2006, at 11:16 AM, Pat Maddox wrote:

Hi --

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 :slight_smile:

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?

Try this:

   module Kernel
     def singleton_class # RCR 231
       class << self; self; end
     end
   end

   class OneShot
     def method_missing(m)
       singleton_class.class_eval do
         define_method(m) { puts m }
       end
     end
   end

   o = OneShot.new
   o.x # method 'x' is created
   o.x # 'x' is printed

David

路路路

On Mon, 7 Aug 2006, Pat Maddox wrote:

--
http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
   ----> SEE SPECIAL DEAL FOR RUBY/RAILS USERS GROUPS! <-----
http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
Ruby for Rails => book, Ruby for Rails
http://www.rubycentral.org => Ruby Central, Inc.

It is close :slight_smile:
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
b = OneShot.new
b.foo

output:
method foo missing!
foo
method foo missing!
foo

Which is what you want, right?

路路路

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 :slight_smile:

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?

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

路路路

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 :slight_smile:

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 :slight_smile:
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?

--
Posted with http://DevLists.com. Sign up and save your mailbox.