defining methods dynamically?

  • Thread starter Kenneth McDonald
  • Start date
K

Kenneth McDonald

Having looked through the Class and Method rdoc, and the Reflection
section of Pickaxe, and still not seeing anything (even though it was
probably right in front of my nose), I'm forced to fall on the mercy of
strangers and ask...how does one add a method to a class while the
program is running?

Thanks,
Ken
 
D

dblack

Hi --

Having looked through the Class and Method rdoc, and the Reflection section
of Pickaxe, and still not seeing anything (even though it was probably right
in front of my nose), I'm forced to fall on the mercy of strangers and
ask...how does one add a method to a class while the program is running?

There's actually no other way to do it :) But I think what you're
looking for is #define_method, which lets you define methods with
dynamically-determined names and also gives you a way to flatten the
variable scope of a method definition.

For example:

str = "greet"
c = Class.new
c.class_eval { define_method(str) { puts "Hello" } }

c.new.greet # Hello


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
P

Peña, Botp

fr: Kenneth McDonald [mailto:[email protected]] :
# Having looked through the Class and Method rdoc, and the Reflection=20
# section of Pickaxe, and still not seeing anything (even though it was=20
# probably right in front of my nose), I'm forced to fall on=20
# the mercy of=20
# strangers and ask...how does one add a method to a class while the=20
# program is running?

this is just one stupid example,

C:\temp>cat test.rb
puts "i'm running..."

class C
puts "i'm running... inside class"
end

puts "i'm running..."

c =3D C.new

puts c.meth rescue puts "no c.meth yet, so this will print"

class C
puts "i'm running... inside class; creating method meth now"
def meth
"yeow!"
end
end

puts "i'm running..."
puts c.meth rescue puts "meth will run now, so this will not print"

puts "i'm running..."
puts c.meth2 rescue puts "method meth2 not yet defined"

puts "let us put the creation on a string..."
puts "i'm running..."
s =3D <<CLASS
class C
puts "i'm running... inside class; creating method second meth2 now"
def meth2
"hehey!"
end
end
CLASS

puts "i'm running..."
eval(s)

puts "now meth2 will run"

puts "i'm running..."
puts c.meth2 rescue puts "meth2 will run, so this will not print"

puts "i'm running..."
puts c.meth3 rescue puts "meth3 will not run yet, so this will print"

puts "now let us put the creation of meth3 using get. i know, but this =
is a stup
id example"
puts "i'm running..."
puts "pls enter a class definition in one line only:"
s =3D gets
eval(s)
puts "i'm running..."
puts c.meth3 rescue puts "now meth3 will run, so this will not print"
puts "i'm running..."
puts "ok"

C:\temp>ruby test.rb
i'm running...
i'm running... inside class
i'm running...
no c.meth yet, so this will print
i'm running... inside class; creating method meth now
i'm running...
yeow!
i'm running...
method meth2 not yet defined
let us put the creation on a string...
i'm running...
i'm running...
i'm running... inside class; creating method second meth2 now
now meth2 will run
i'm running...
hehey!
i'm running...
meth3 will not run yet, so this will print
now let us put the creation of meth3 using get. i know, but this is a =
stupid exa
mple
i'm running...
pls enter a class definition in one line only:
class C; def meth3; "hello from meth3"; end;end
i'm running...
hello from meth3
i'm running...
ok

C:\temp>

kind regards -botp
 
V

vasudevram

Kenneth said:
Having looked through the Class and Method rdoc, and the Reflection section of Pickaxe, and still not seeing anything (even though it was probably right in front of my nose), I'm forced to fall on the mercy of strangers and ask...how does one add a method to a class while the program is running?

I think there are at least two ways to do it, both of which I've seen
in the Ruby Cookbook.

One uses define_method, as one of the other posters said; the other
uses module_eval, IIRC. There's also an example using module_eval in
the Pickaxe - 2nd edition.

Vasudev Ram
http://www.dancingbison.com
http://jugad.livejournal.com
http://sourceforge.net/projects/xtopdf
 
D

dblack

Hi --

David,

I do not follow what you mean by "flatten the variable scope of a method
definition".
Could you please explain what this means a bit?

Sure. Let's say you want to do:

a = 1
class C
def show_a
a # won't work
end
end

The definition of a won't make it into the scope of the method
definition #show_a, because both the class keyword and the def keyword
start a new local scope.

However, class_eval and define_method are both permeable, as to scope.
So you can do:

a = 1
class C; end
C.class_eval { define_method:)show_a) { a } }

C.new.show_a # 1

The a inside the block given to define_method is the same a that I
defined in the first line. That's what I mean by flattening the
variable scope.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
P

Peña, Botp

From: Wayne E. Seguin [mailto:[email protected]] :
# That makes complete sense.=20

careful. me thinks define_method is verry different from normal ruby =
methods,
a. it flattens scope. variables just creep inside
b. it does not check for arguments

ergo, i'd prefer define_method be renamed to define_method!=20

i suggest define_method should be documented clearly. it could hang =
nubies, like me :)

module_eval-ing may be closer to ruby methods.

eg,

C:\family\ruby>cat test.rb
a =3D 1
class C; end
C.class_eval {define_method:)show_a) {a}}

# this will not err; define_method methods do not check arguments!
puts C.new.show_a(1)

# just to show difference...
class C
def show_a2
a
end
end

# this will err as usual; i just put a rescue to let prg continue
puts C.new.show_a2(1) rescue puts "wrong number of args !!"

# I think module_eval is a closer match to normal methods
s =3D %q{def show_a(); a ; end}
C.module_eval(s)

# vars will not creep
puts C.new.show_a() rescue puts "undefined a !!"
# and args will be checked
puts C.new.show_a(1) rescue puts "wrong number of args !!"

C:\family\ruby>ruby test.rb
1
wrong number of args !!
undefined a !!
wrong number of args !!

C:\family\ruby>


kind regards -botp
 

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,754
Messages
2,569,527
Members
44,998
Latest member
MarissaEub

Latest Threads

Top