Adding methods to a singleton dynamically


#1

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


#2

Hi –

On Sun, 12 Mar 2006, Mike A. wrote:

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:

}
}

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


David A. Black (removed_email_address@domain.invalid)
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


#3

Hi –

On Sun, 12 Mar 2006, Mike A. wrote:

view = Object::const_get( key[1] ).new
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

David A. Black (removed_email_address@domain.invalid)
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


#4

removed_email_address@domain.invalid 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