define_method to add a Class method?

W

walter

How do you use define_method (or an equivalent) to add a method to a
Class.

I want to create a class from a Database result set at runtime. I
was doing this by building a string and the evaling it, which works,
but wasn't all that rubyish and was ugly.

I am now using an Anonymous class ie Class.new{...} and everything is
great except I can't seem to create a class method this way.

I know I am missing something quite obvious, I just can't seem to
find it.

Any pointers would be greatly appreciated.


Thanks,

Walt
*****************************************************
Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : (e-mail address removed)
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284
*****************************************************
 
S

Sean O'Dell

How do you use define_method (or an equivalent) to add a method to a
Class.

I want to create a class from a Database result set at runtime. I
was doing this by building a string and the evaling it, which works,
but wasn't all that rubyish and was ugly.

I am now using an Anonymous class ie Class.new{...} and everything is
great except I can't seem to create a class method this way.

I know I am missing something quite obvious, I just can't seem to
find it.

Any pointers would be greatly appreciated.

I'd stick with eval; it does the job. Something like this should work just
fine:

class_name = "MyClass"
code = "print 'Hello, world!\n'"
method_name = "my_method"

eval_string = <<-EVAL
class #{class_name}
def #{method_name}
#{code}
end
end
EVAL

eval eval_string

o = MyClass.new
o.my_method #=> "Hello, world!\n"


Sean O'Dell
 
W

walter

I'd stick with eval; it does the job. Something like this should work
just fine:

class_name = "MyClass"
code = "print 'Hello, world!\n'"
method_name = "my_method"

eval_string = <<-EVAL
class #{class_name}
def #{method_name}
#{code}
end
end
EVAL

eval eval_string

o = MyClass.new
o.my_method #=> "Hello, world!\n"


Sean O'Dell


That was how original version worked, and I can seem to port
everything except the creation of the class methods using the
Class.new{...} syntax. It just seems as if I am missing something.
Can we not add a class method using define_method. I have tried it
in combination with instance_eval, module_eval, directly on the
class, within the class, etc but so far no luck.

I guess I just want to know if it can be done using a define_ method
or do we _have_ to use eval to add a class method this way.


Thanks,


Walt
*****************************************************
Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : (e-mail address removed)
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284
*****************************************************
 
S

Sean O'Dell

That was how original version worked, and I can seem to port
everything except the creation of the class methods using the
Class.new{...} syntax. It just seems as if I am missing something.
Can we not add a class method using define_method. I have tried it
in combination with instance_eval, module_eval, directly on the
class, within the class, etc but so far no luck.

I guess I just want to know if it can be done using a define_ method
or do we _have_ to use eval to add a class method this way.

Well, I can add a method to that same class I created with an eval, this way:

class MyClass
define_method:)my_method2) do
print("Hello, world, again!\n")
end
end

o.my_method2 #=> "Hello, world, again!\n"


Sean O'Dell
 
W

walter

Well, I can add a method to that same class I created with an eval,
this way:

class MyClass
define_method:)my_method2) do
print("Hello, world, again!\n")
end
end

o.my_method2 #=> "Hello, world, again!\n"


Sean O'Dell

that does work, but you are adding a method to an instance of the
class. I want to add a method to the class itself, and I want to be
able to do it to an anonymous class.

At this point this is purely academic. I have a working version, I
just think there is something I am not understanding as to why I can
seem to be able to dynamically add a class method. I can add dynamic
instance methods fine.

I am looking for the equivalent of

theClass = Class.new do
def self.class_method
puts "class_method called"
end
end

theClass.class_method

but using define dynamically (it would really be returning something
that was passed into the method that is creating the class)

def create(data)
Class.new{define_method('self.class_method', lamda{data.dup})}
end

puts create(%w{we made it}).class_method.join(" ")

and get "we made it"

that's the gist of what I am trying to do. As I said, its purely
academic at this point, just a curiosity.


Thanks,

Walt
*****************************************************
Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : (e-mail address removed)
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284
*****************************************************
 
P

Paul Brannan

I'd stick with eval; it does the job. Something like this should work
just fine:

Using eval doesn't allow the method to be executed in the context in
which it was created, which is what define_method allows. You can make
it work by assigning a proc to a variable and then calling that proc
from the eval'd code, but that's overkill, since define_method does the
job:

class Foo
s = class << self; self; end
l = 42 # local variable
s.class_eval do
define_method:)foo) do
puts "here: #{l}"
end
end
end

Foo.foo #=> here: 42

We first get the singleton class and assign it to s, then call
define_method for the singleton class (we could call define_method from
inside the class << self block, but then we wouldn't have access to
local variables).

Paul
 
P

Pit Capitain

<snip>
I want to add a method to the class itself, and I want to be
able to do it to an anonymous class.

c = Class.new do
class << self
define_method :m do p "m" end
end
end

c.m # ==> "m"


HTH

Regards,
Pit
 
W

walter

c = Class.new do
class << self
define_method :m do p "m" end
end
end

c.m # ==> "m"


HTH

Regards,
Pit

Excellent, That does work as expected. I did try that previously,
but my error was trying to pass in data to that context.

def create(data)
Class.new do
my_lambda = lambda{data}
define_method("instance", my_lambda) #this is fine

class << self
define_method("ok_method"){"ok method"} #this is fine

# the next method will throw a
# undefined local variable or method `my_lambda'
# for #<Class:#<Class:0x2a67840>> (NameError)
define_method("data_passed_in", my_lambda)
end
end
end
puts create("data").data_passed_in


I tried several similar variations. I'll have to look into the
scoping rules more to see how to overcome this. It just shows me I
need to study the language more.


Thanks everyone,


Walt
*****************************************************
Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : (e-mail address removed)
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284
*****************************************************
 
N

nobu.nokada

Hi,

At Sat, 3 Jul 2004 08:46:48 +0900,
def create(data)
Class.new do
my_lambda = lambda{data}
define_method("instance", my_lambda) #this is fine
(class << self; self; end).class_eval do
define_method("ok_method"){"ok method"} #this is fine
define_method("data_passed_in", my_lambda)
end
end
end

Or:

class Result
def instance
self.class.data_passed_in
end
class << self
def ok_method
"ok_method"
end
def data_passed_in
@data
end
end
end

def create(data)
Class.new(Result) {@data = data}
end
 
W

walter

Hi,

At Sat, 3 Jul 2004 08:46:48 +0900,

(class << self; self; end).class_eval do

Or:

class Result
def instance
self.class.data_passed_in
end
class << self
def ok_method
"ok_method"
end
def data_passed_in
@data
end
end
end

def create(data)
Class.new(Result) {@data = data}
end


Thanks Nobu,

The part I missed was setting @data within the scope of the new
class.
so this now works..
def create(data)
Class.new do
@data = data
class << self
define_method("data_passed_in"){@data}
end
define_method("q"){"we are in q"}
end
end

create("some data").data_passed_in

Now that I look at it this morning I can't believe I missed that.
Also I didn't realize that you could pass in a Class while creating
an anonymous class and extend that in the body of new. Very cool.


Thanks again, I knew I was missing something.


Walt
*****************************************************
Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : (e-mail address removed)
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284
*****************************************************
 

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

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top