Object methods

Hello there. :slight_smile:

Ok, I know I can do this to add a method (and a class)
to an object:

irb(main):001:0> s = “Testing!”
=> “Testing!”
irb(main):002:0> class <<s
irb(main):003:1> def says
irb(main):004:2> puts “s says:”+self
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> s.says
s says:Testing!
=> nil
irb(main):008:0> x = “Another test.”
=> “Another test.”
irb(main):009:0> x.says
NoMethodError: undefined method `says’ for “Another
test.”:String
from (irb):9
from :0
irb(main):010:0>

My question is, dinamically, how to do that? Just like
this:

irb(main):010:0> x.class.class_eval %q(def x.says()
puts “x says:”+self end)
=> nil
irb(main):011:0> x.says
x says:Another test.

Or there is another shorter way to do that, with an
object? To build an object method with some parameters
like a string or a Proc?

Thanks! :slight_smile:

Eustaquio Rangel de Oliveira J wrote:

irb(main):005:2> end
from (irb):9
x says:Another test.

Or there is another shorter way to do that, with an
object? To build an object method with some parameters
like a string or a Proc?

I’m not sure what exactly you’re after. Do you mean

class String
def says
print "s says: ", self, “\n”
end
end

?

robert

Hello, Robert!

I’m not sure what exactly you’re after. Do you mean
class String
def says
print "s says: ", self, “\n”
end
end
?

Not really, I want to create a new method on the
object, after it’s created, but not on the class. As
the previous example of

s = “Testing”
class <<s
def says
print "s says: ", self, “\n”
end
end

where it creates the method (and all that metaclass
stuff).

At this point just, just s have the “says” method, not
the class String or any other String object that was
created or will be created. Using

s.class.class_eval %q(def x.says() puts “x says:”+self
end)

have the same effect, but what I like to know if there
is another way to do that. I mean, create a method on
a specific object (on this case, just “s”), not on the
class.

Best regards,

Eustaquio Rangel de Oliveira J wrote:

end

Home - Beings
Usuário GNU/Linux no. 224050

Hmmm…you can use Object#extend to add the instance methods from a
module. Is that what you’re looking for?

Oooooops, sorry for this. The correct example is:

s.class.class_eval %q(def s.says() puts “s says:”+self
end)

I copied the wrong part of my previous email. :-p

Best regards,

On Sun, 26 Mar 2006, Eustaquio Rangel de Oliveira J wrote:

Not really, I want to create a new method on the
where it creates the method (and all that metaclass
is another way to do that. I mean, create a method on
a specific object (on this case, just “s”), not on the
class.

How about:

def s.says
puts “s says: #{self}”
end

?

David


David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! Ruby for Rails

Hi, David.

How about:

def s.says
puts “s says: #{self}”
end
?

Yes, this way works, but I need to make it
dinamically, for example (don’t know if it’s a valid
situation, just curious about) reading the code from a
string from a file. If I type the code above it’s ok,
but I want to load the new methods from somewhere.

Best regards,

Hi, Tim!

Hmmm…you can use Object#extend to add the instance
methods from a
module. Is that what you’re looking for?

But on that way I need a previou module with the
methods. What I want is to create the methods on a
certain object, “on the air”, I mean, from a string or
something like that.

The s.class.class_eval make this kind of
thing, but I was curious about some other way to do
that. :slight_smile:

Best regards,

Hi Robert!

s.class.class_eval %q(def x.says() puts “x
says:”+self
end)
This doesn’t work for me. You define a method “say”
for an instance “x”
in the scope of the class. You probably want
something else.

I noticed that I made a mistake there and correct it
on another email few seconds after that one. Sorry
about that. My fault.

As I told on the other email, the correct thing is

s.class.class_eval %q(def s.says() puts “s says:”+self
end)

So I create a method “says” only on the object s (not
on the class String where it belongs to).

It would certainly help if you tell us what problem
you are trying to solve.

Ok, not really a problem, I was just curious about it.

Let’s imagine that I need a way to create methods on
specific objects, not on their classes. The methods
are stored on some file or the user type it when using
the program (ok, I know the security concerns about
that :-), and I find them later using some reflection
and respond_to calls.

So at some point the user knows (again, don’t know if
its a valid situation) that there are some String
objects hangin’ there, s and x, and says “hey, add
this method I defined here on this text field, as a
string, to the s object, but just to it, not to its
class or other String objects”. On this case, knowing
that I want to create the method just on s, and it’s a
String, I can use

String.class_eval %q(def s.says() puts “s says:”+self
end)

to make this works, and ask for some reavaliation of
the current objects, where it will tell me that the s
object, yes, have a “says” method there.

s.respond_to?(:says)

It works this way, I was just curious if there is not
an object method to do that, not using the class to
make it works. But works this way because of the need
to add a virtual class to s to hold the says() method,
right?

Best regards,

Eustaquio Rangel de Oliveira J [email protected] schrieb:

Let’s imagine that I need a way to create methods on
specific objects, not on their classes. The methods
are stored on some file or the user type it when using
the program (ok, I know the security concerns about
that :-), and I find them later using some reflection
and respond_to calls.

Erm, maybe you’re searching for “instance_eval”?

Patrick

Erm, maybe you’re searching for “instance_eval”?

That’s it!

irb(main):001:0> s = “Testing!”
=> “Testing!”
irb(main):002:0> s.instance_eval %q(def says() puts “s
says:”+self end)
=> nil
irb(main):003:0> s.says
s says:Testing!

Thanks, Patrick!

I read about instance_eval some time ago and forgot
completly about it! I knew there there was an easier
way to do that without class_eval, but … man, what a
headache. :slight_smile:

Thanks for the help guys. :slight_smile:

Best regards,

Eustaquio Rangel de Oliveira J wrote:

Not really, I want to create a new method on the
where it creates the method (and all that metaclass
stuff).

At this point just, just s have the “says” method, not
the class String or any other String object that was
created or will be created. Using

s.class.class_eval %q(def x.says() puts “x says:”+self
end)

have the same effect,

This doesn’t work for me. You define a method “say” for an instance “x”
in the scope of the class. You probably want something else.

but what I like to know if there
is another way to do that. I mean, create a method on
a specific object (on this case, just “s”), not on the
class.

def s.says
puts "I say " + self
end

It would certainly help if you tell us what problem you are trying to
solve.

Cheers

robert

And of course here’s how to do it with class_eval,
just to make life
more exciting:
(class << a; self; end).class_eval

Yes, that is almost my first example of the problem.

The point is that I forgot completely about
instance_eval, do you know those moments when you need
to use something, is sure that there is a (or other)
way to do the it but don’t remember how to do it? I
knew about the <<, virtual classes, class_eval, but
forgot instance_eval. :slight_smile:

I hate this kind of “blocks” and “blanks”. Maybe I
need some vacations. :slight_smile:

The good thing is that we can ask for our good friends
about that. Thanks, dudes. :slight_smile:

On Mar 26, 2006, at 11:07 AM, Eustaquio Rangel de Oliveira J wrote:

I read about instance_eval some time ago and forgot
completly about it! I knew there there was an easier
way to do that without class_eval, but … man, what a
headache. :slight_smile:

And of course here’s how to do it with class_eval, just to make life
more exciting:

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