defining a singleton method dynamically

N

Nilesh Trivedi

[Note: parts of this message were removed to make it a legal post.]

How do I define a singleton method dynamically?

I have code similar to this:

def foo(obj,label)
def obj.name; label; end #we want to define a singleton method called
"name" on obj which returns the value in label
puts obj.name #this is an example. Actually I have some code here which
expects this singleton method in obj
end

When I try to run this as foo(Object.new,"xyz"), it throws a "NameError:
undefined local variable or method `label' for #<Object:0xb7b02018>" whereas
I want it to print "xyz" to screen.

Of course, line 2 in method foo is not correct. But what is the correct way?
 
D

David A. Black

Hi --

How do I define a singleton method dynamically?

I have code similar to this:

def foo(obj,label)
def obj.name; label; end #we want to define a singleton method called
"name" on obj which returns the value in label
puts obj.name #this is an example. Actually I have some code here which
expects this singleton method in obj
end

When I try to run this as foo(Object.new,"xyz"), it throws a "NameError:
undefined local variable or method `label' for #<Object:0xb7b02018>" whereas
I want it to print "xyz" to screen.

Of course, line 2 in method foo is not correct. But what is the correct way?

def starts a new local scope, so it won't see label. You need to get
into obj's singleton class, using code blocks rather than class and
def blocks:

def foo(obj, label)
(class << obj; self; end).class_eval do
define_method("name") { label }
end
end

You could also do something with eval but I prefer to use the code
block approach rather than the string-eval'ing approach.

(Still hoping for Object#singleton_class to make the access to the
singleton class a little less awkward :)


David

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Ruby/Rails training, mentoring, consulting, code-review
Latest book: The Well-Grounded Rubyist (http://www.manning.com/black2)

September Ruby training in NJ has been POSTPONED. Details to follow.
 
N

Nilesh Trivedi

[Note: parts of this message were removed to make it a legal post.]

How do I define a singleton method dynamically?

I have code similar to this:

def foo(obj,label)
def obj.name; label; end #we want to define a singleton method called
"name" on obj which returns the value in label
puts obj.name #this is an example. Actually I have some code here which
expects this singleton method in obj
end

When I try to run this as foo(Object.new,"xyz"), it throws a "NameError:
undefined local variable or method `label' for #<Object:0xb7b02018>" whereas
I want it to print "xyz" to screen.

Of course, line 2 in method foo is not correct. But what is the correct
way?

Replacing line 2 by:

obj.instance_eval "def name; '#{label}'; end"

does get the behaviour that I want. Is this the best way to do this or is
there a better, cleaner way?

cheers
nilesh
 
D

David A. Black

Hi --

Replacing line 2 by:

obj.instance_eval "def name; '#{label}'; end"

does get the behaviour that I want. Is this the best way to do this or is
there a better, cleaner way?

It may be overkill, but I pretty much always choose the block form of
*_eval rather than the string form, as per my response of a couple of
minutes ago. If you're going to eval strings, you could also do:

eval "def obj.name; '#{label}'; end"


David

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Ruby/Rails training, mentoring, consulting, code-review
Latest book: The Well-Grounded Rubyist (http://www.manning.com/black2)

September Ruby training in NJ has been POSTPONED. Details to follow.
 
J

James Edward Gray II

Hi --



def starts a new local scope, so it won't see label. You need to get
into obj's singleton class, using code blocks rather than class and
def blocks:

def foo(obj, label)
(class << obj; self; end).class_eval do
define_method("name") { label }
end
end

You could also do something with eval but I prefer to use the code
block approach rather than the string-eval'ing approach.

(Still hoping for Object#singleton_class to make the access to the
singleton class a little less awkward :)

I agree, but it's needed a little less in Ruby 1.9 which adds
defined_singleton_method(). Thus, in 1.9 your code could be:

def foo(obj, label)
obj.define_singleton_method:)name) { label }
end

As a side topic, the fact that this method was added seems to kill the
argument about why we can't have singleton_class(). As I understand
it, the method we want is never added because we aren't sure if the
name is right yet. Seems like we're committed to the name at this
point and might as well just get on with defining the methods that
help us.

James Edward Gray II
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top