Adding methods to a singleton dynamically

I'm building a view hierarchy from a file, and I would like it to add getter methods for every subview created. For example, I should be able to write:

window.bottom_panel.save_button.left = 20

I played around with singleton classes and define_method, am I close? I wonder if it is illegal to do 'class << self end' within a method - I get the error 'class definition in method body'

hierarchy.each do |key, value|
   view = Object::const_get( key[1] ).new

   class << self end

   self.class.class_eval do
     define_method( key[1] ) do
       return view
     end
   end
end

hierarchy = {
   [:bottom_panel, :Panel] => {
     [:save_button, :Button] => {}
   }
}

Thanks,
Mike

Hi --

I'm building a view hierarchy from a file, and I would like it to add getter methods for every subview created. For example, I should be able to write:

window.bottom_panel.save_button.left = 20

I played around with singleton classes and define_method, am I close? I wonder if it is illegal to do 'class << self end' within a method - I get the error 'class definition in method body'

hierarchy.each do |key, value|
view = Object::const_get( key[1] ).new

class << self end

I get a syntax error on that; I think you need a semi-colon after
'self'. However, even with the semi-colon, the expression doesn't do
anything. (It just opens a class definition block and then closes
it.) Do you want to capture the singleton class? If so, you would
do:

   singleton_class = (class << self; self; end)

Inside the block, 'self' is the class itself. (And vote for your
local RCR 231 :slight_smile:

self.class.class_eval do
   define_method( key[1] ) do
     return view
   end
end
end

hierarchy = {
[:bottom_panel, :Panel] => {
   [:save_button, :Button] => {}
}
}

Does that last bit actually come first?

I haven't quite grasped what you want to do (due to tiredness, I
think), but maybe the above will help.

David

···

On Sun, 12 Mar 2006, Mike Austin wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black

Hi --

I'm building a view hierarchy from a file, and I would like it to add getter methods for every subview created. For example, I should be able to write:

window.bottom_panel.save_button.left = 20

I played around with singleton classes and define_method, am I close? I wonder if it is illegal to do 'class << self end' within a method - I get the error 'class definition in method body'

hierarchy.each do |key, value|
view = Object::const_get( key[1] ).new

class << self end

self.class.class_eval do
   define_method( key[1] ) do
     return view
   end
end
end

hierarchy = {
[:bottom_panel, :Panel] => {
   [:save_button, :Button] => {}
}
}

I just *know* there's a way to do this with inject... :slight_smile: But
meanwhile, see if this is of any use. It's a whole little
self-contained simulation.

def cascade_from_hierarchy(base,hierarchy)
   label, kind = *hierarchy.keys[0]
   rest = hierarchy.values[0]
   view = kind.new

   (class << base; self; end).class_eval do
     define_method(label) { view }
   end

   cascade_from_hierarchy(view,rest) unless rest.empty?
end

class Panel; end
class Button; end
class Window; end

window = Window.new
hierarchy = {
   [:bottom_panel, Panel] => {
     [:save_button, Button] => {}
   }
}

cascade_from_hierarchy(window,hierarchy)

p window.bottom_panel.save_button # #<Button:0x1ceb58>

__END__

David

···

On Sun, 12 Mar 2006, Mike Austin wrote:
--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black

dblack@wobblini.net wrote:
> I just *know* there's a way to do this with inject... :slight_smile: But
> meanwhile, see if this is of any use. It's a whole little
> self-contained simulation.

Thanks, that does the job. I was a little unclear of how << worked but now I get it.

Mike

dblack@wobblini.net wrote:

···

Hi --

On Sun, 12 Mar 2006, Mike Austin wrote:

I'm building a view hierarchy from a file, and I would like it to add getter methods for every subview created. For example, I should be able to write:

window.bottom_panel.save_button.left = 20

I played around with singleton classes and define_method, am I close? I wonder if it is illegal to do 'class << self end' within a method - I get the error 'class definition in method body'

hierarchy.each do |key, value|
view = Object::const_get( key[1] ).new

class << self end

self.class.class_eval do
   define_method( key[1] ) do
     return view
   end
end
end

hierarchy = {
[:bottom_panel, :Panel] => {
   [:save_button, :Button] => {}
}
}

I just *know* there's a way to do this with inject... :slight_smile: But
meanwhile, see if this is of any use. It's a whole little
self-contained simulation.

def cascade_from_hierarchy(base,hierarchy)
  label, kind = *hierarchy.keys[0]
  rest = hierarchy.values[0]
  view = kind.new

  (class << base; self; end).class_eval do
    define_method(label) { view }
  end

  cascade_from_hierarchy(view,rest) unless rest.empty?
end

class Panel; end
class Button; end
class Window; end

window = Window.new
hierarchy = {
  [:bottom_panel, Panel] => {
    [:save_button, Button] => {}
  }
}

cascade_from_hierarchy(window,hierarchy)

p window.bottom_panel.save_button # #<Button:0x1ceb58>

__END__

David