Method_missing question

Currently, I have a class that has a bunch of methods (that a GUI does
a callback on) that are like

  def menu_zoom_100_activate
    @display.zoom(100)
  end

  def menu_zoom_250_activate
    @display.zoom(250)
  end

  def menu_zoom_500_activate
    @display.zoom(500)
  end

Could I use #method_missing to make this better?

Why not just call @display.zoom(500)?

···

On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

Currently, I have a class that has a bunch of methods (that a GUI does
a callback on) that are like

  def menu_zoom_100_activate
    @display.zoom(100)
  end

  def menu_zoom_250_activate
    @display.zoom(250)
  end

  def menu_zoom_500_activate
    @display.zoom(500)
  end

Could I use #method_missing to make this better?

--
rick
http://techno-weenie.net

Joe Van Dyk wrote:

Could I use #method_missing to make this better?

Yep. Try this out:

class Display
  def zoom(i)
    puts "Zooming to #{i}"
  end
end

class AppWindow
  def initialize()
    @display = Display.new
  end

  def method_missing(method, *args)
    case method.id2name
    when /menu_zoom_(\d+)_activate/
      @display.zoom($1.to_i)
    else
      puts "Unknown method: #{method}"
    end
  end
end

if $0 == __FILE__
  app = AppWindow.new
  app.menu_zoom_100_activate
  app.menu_zoom_250_activate
  app.menu_zoom_500_activate
  app.blah
end

Joe Van Dyk wrote:

Currently, I have a class that has a bunch of methods (that a GUI does
a callback on) that are like

  def menu_zoom_100_activate
    @display.zoom(100)
  end

  def menu_zoom_250_activate
    @display.zoom(250)
  end

  def menu_zoom_500_activate
    @display.zoom(500)
  end

Could I use #method_missing to make this better?

you could do that like this:

def method_missing(methodname, *args)
  if methodname=~/menu_zoom(\d+)_activate/
    @display.zoom($1.to_i)
  else
    super
  end
end

Because when a GUI button is clicked, I need to call a particular
method of a particular class. I don't think I can give it an
argument.

···

On 4/29/05, Rick Olson <technoweenie@gmail.com> wrote:

Why not just call @display.zoom(500)?

On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
> Currently, I have a class that has a bunch of methods (that a GUI does
> a callback on) that are like
>
> def menu_zoom_100_activate
> @display.zoom(100)
> end
>
> def menu_zoom_250_activate
> @display.zoom(250)
> end
>
> def menu_zoom_500_activate
> @display.zoom(500)
> end
>
> Could I use #method_missing to make this better?
>

> Why not just call @display.zoom(500)?
>
> > Currently, I have a class that has a bunch of methods (that a GUI does
> > a callback on) that are like
> >
> > def menu_zoom_100_activate
> > @display.zoom(100)
> > end
> >
> > def menu_zoom_250_activate
> > @display.zoom(250)
> > end
> >
> > def menu_zoom_500_activate
> > @display.zoom(500)
> > end
> >
> > Could I use #method_missing to make this better?
> >

Because when a GUI button is clicked, I need to call a particular
method of a particular class. I don't think I can give it an
argument.

Actually, (I'm using Glade) I have this:

app_window = AppWindow.new
GladeXML.new("app.glade") { |handler| app_window.method(handler) }

Where AppWindow is a class that contains all the methods that are
defined in the glade file. In the glade file are methods being
registered like "menu_zoom_250_activate", "menu_zoom_500_activate" and
so on.

If a particular method that's contained in the glade file isn't
defined in the AppWindow class, I get a "undefined method '<some

' for class AppWindow" upon the start of the application.

I added AppWindow#method_missing that just prints out the missing
method, but that didn't seem to solve anything.

Perhaps it would be best to have a single method in AppWindow that
took all the methods (as a string) that were defined in the glade file
and executed the appropriate action?

So,

GladeXML.new("app.glade") { |handler| app_window.execute_method(handler) }

class AppWindow
  def execute_method(method)
    case method
    when /menu_zoom_(\d+)_activate/
      @display.zoom($1.to_i)
    when "something_else"
      # do something else
    end
  end
end

···

On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

On 4/29/05, Rick Olson <technoweenie@gmail.com> wrote:
> On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

Nuts, I tried that, and AppWindow#execute_method is being run at
application start for each method defined in the glade file, and now
none of the GUI events do anything. Hm.

···

On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
> On 4/29/05, Rick Olson <technoweenie@gmail.com> wrote:
> > Why not just call @display.zoom(500)?
> >
> > On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:
> > > Currently, I have a class that has a bunch of methods (that a GUI does
> > > a callback on) that are like
> > >
> > > def menu_zoom_100_activate
> > > @display.zoom(100)
> > > end
> > >
> > > def menu_zoom_250_activate
> > > @display.zoom(250)
> > > end
> > >
> > > def menu_zoom_500_activate
> > > @display.zoom(500)
> > > end
> > >
> > > Could I use #method_missing to make this better?
> > >
>
> Because when a GUI button is clicked, I need to call a particular
> method of a particular class. I don't think I can give it an
> argument.
>

Actually, (I'm using Glade) I have this:

app_window = AppWindow.new
GladeXML.new("app.glade") { |handler| app_window.method(handler) }

Where AppWindow is a class that contains all the methods that are
defined in the glade file. In the glade file are methods being
registered like "menu_zoom_250_activate", "menu_zoom_500_activate" and
so on.

If a particular method that's contained in the glade file isn't
defined in the AppWindow class, I get a "undefined method '<some
>' for class AppWindow" upon the start of the application.

I added AppWindow#method_missing that just prints out the missing
method, but that didn't seem to solve anything.

Perhaps it would be best to have a single method in AppWindow that
took all the methods (as a string) that were defined in the glade file
and executed the appropriate action?

So,

GladeXML.new("app.glade") { |handler| app_window.execute_method(handler) }

class AppWindow
  def execute_method(method)
    case method
    when /menu_zoom_(\d+)_activate/
      @display.zoom($1.to_i)
    when "something_else"
      # do something else
    end
  end
end

Joe Van Dyk wrote:

···

On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

On 4/29/05, Rick Olson <technoweenie@gmail.com> wrote:

Why not just call @display.zoom(500)?

On 4/29/05, Joe Van Dyk <joevandyk@gmail.com> wrote:

Currently, I have a class that has a bunch of methods (that a GUI does
a callback on) that are like

def menu_zoom_100_activate
   @display.zoom(100)
end

def menu_zoom_250_activate
   @display.zoom(250)
end

def menu_zoom_500_activate
   @display.zoom(500)
end

Could I use #method_missing to make this better?

Because when a GUI button is clicked, I need to call a particular
method of a particular class. I don't think I can give it an
argument.

Actually, (I'm using Glade) I have this:

app_window = AppWindow.new
GladeXML.new("app.glade") { |handler| app_window.method(handler) }

Where AppWindow is a class that contains all the methods that are
defined in the glade file. In the glade file are methods being
registered like "menu_zoom_250_activate", "menu_zoom_500_activate" and
so on.

If a particular method that's contained in the glade file isn't
defined in the AppWindow class, I get a "undefined method '<some

' for class AppWindow" upon the start of the application.

I added AppWindow#method_missing that just prints out the missing
method, but that didn't seem to solve anything.

Perhaps it would be best to have a single method in AppWindow that
took all the methods (as a string) that were defined in the glade file
and executed the appropriate action?

So,

GladeXML.new("app.glade") { |handler| app_window.execute_method(handler) }

class AppWindow
def execute_method(method)
   case method
   when /menu_zoom_(\d+)_activate/
     @display.zoom($1.to_i)
   when "something_else"
     # do something else
   end
end
end

Nuts, I tried that, and AppWindow#execute_method is being run at
application start for each method defined in the glade file, and now
none of the GUI events do anything. Hm.

How about going back to you method_missing idea, and then in method_missing, parsing the name of the method that was being called and converting that to a method call that you eval.

For example: if the method being called was "display_zoom_250", convert that to the string "@display.zoom(250)" and then eval that string.

Curt

Joe Van Dyk schrieb:

Currently, I have a class that has a bunch of methods (that a GUI does
a callback on) that are like

def menu_zoom_100_activate
   @display.zoom(100)
end

def menu_zoom_250_activate
   @display.zoom(250)
end

def menu_zoom_500_activate
   @display.zoom(500)
end

Could I use #method_missing to make this better?

You should be able to use method_missing, but you could also do something like

   class Handler

     [ 100, 250, 500 ].each do |factor|
       define_method("menu_zoom_#{factor}_activate") do
         @display.zoom(factor)
       end
     end

   end

or for some more syntax sugar define a class method

   class Handler

     class << self
       def zoom_methods(*factors)
         ...see above...
       end
     end

     zoom_methods 100, 250, 500

   end

Regards,
Pit

DING DING DING.

The above worked perfectly. Thanks!

···

On 4/29/05, Pit Capitain <pit@capitain.de> wrote:

Joe Van Dyk schrieb:
>
>Currently, I have a class that has a bunch of methods (that a GUI does
>a callback on) that are like
>
> def menu_zoom_100_activate
> @display.zoom(100)
> end
>
> def menu_zoom_250_activate
> @display.zoom(250)
> end
>
> def menu_zoom_500_activate
> @display.zoom(500)
> end
>
>Could I use #method_missing to make this better?

You should be able to use method_missing, but you could also do
something like

   class Handler

     [ 100, 250, 500 ].each do |factor|
       define_method("menu_zoom_#{factor}_activate") do
         @display.zoom(factor)
       end
     end

   end