my face
About Me

Published Posts

All Posts

New Post


View by Tag:

interviewing, code, testing, philosophy, blog, wantmyjob, virtualization, railsmud, heroku, ruby, published, neoarchaeology, railsgame, rails, juggernaut, astrino, cheaptoad, public


FeedBurner picture


Online Portfolio

Resume

Profile on LinkedIn

Recommend Me

The 'Self' Variable and Eval in Ruby

Created: 2007-11-12 21:00:18 UTC / Updated: 2009-06-22 20:52:51 UTC

Imported from WordPress

Originally posted on 2007-11-12 21:00:18

Ruby metaprogramming tends to involve code in classes, modules and functions. It can involve defining regular functions and "self.whatever" functions. It's easy to get a little lost. So I'll talk a bit about the "self" variable and what it means at different times.

In Ruby, "self" means the current object. Whenever you call a function, Ruby is implicitly finding it under 'self'. Your top-level object is an instance of class Object, but mostly it's just another object. That top-level object just happens to be the value of "self" at the top level.

Eval works in Ruby pretty much like in any other language. It evaluates the code in the current context. You can do some cute tricks with bindings (sets of variable values), but basically it's as though you'd just typed the code at the current location. Eval's close relatives class_eval and instance_eval are similar. If you have a class name (say Object) and follow it with .class_eval and then a string or a block of code, it's as though you had opened up the class and were writing code in that object, so you can do things like defining methods for the class. If you take an object instance (like, say, k = Object.new) and follow it with .instance_eval (so, k.instance_eval) and then a string or block of code, you're evaluating within the context of that object, so self is set to that object. For instance:

class MyClass

attr_accessor :name, :age
end

MyClass.class_eval do
def test
print "Test function!\n"
end
end

myc = MyClass.new
myc.name = "Barry"
raise "This shouldn't happen!" unless myc.instance_eval { @name } == "Barry"


There are some times that it's probably not clear what self is. For instance, you're probably not used to the idea that defining a class in Ruby is still just running Ruby code, so it may not be obvious what "self" means inside a class declaration. So let's have a look:
class Bob

print "Class Bob:\n"
print "Self is #{self.inspect}\n"
print "Type of self is #{self.class}\n"
end

module Sam
print "\nModule Sam:\n"
print "Self is #{self.inspect}\n"
print "Type of self is #{self.class}\n"
end

class << Bob
print "\nSingleton for class Bob:\n"
print "Self is #{self.inspect}\n"
print "Type of self is #{self.class}\n"
print "Superclass of self is #{self.class.superclass}\n"
end


When you run this in Ruby, you get the following:
Class Bob:

Self is Bob
Type of self is Class

Module Sam:
Self is Sam
Type of self is Module

Singleton for class Bob:
Self is #<Class:Bob>
Type of self is Class
Superclass of self is Module


So - when you're defining a class or module, 'self' is the class or module you're defining. Makes sense. And that last thing, in case you're not familiar with it, is a singleton class, or eigenclass (you'll see both names if you look). In Ruby, every individual object is allowed to have a singleton class associated with it where you can define functions. That means every instance of every class is allowed to have extra functions that are only called for that object, not for other instances of the same class. When you're defining an eigenclass, the 'self' variable points to that eigenclass. The eigenclass is just a class (see? Its type is 'Class') like the one above. Its parent class isn't 'Class' or anything. But it knows that it's special, because it prints out funny, as '<Class:Bob>' rather than just 'Bob'.

And now you know how the 'self' variable works, no matter where you are in Ruby. And that means you know how to find out where the functions you're calling are defined, no matter whether you're defining a method or defining a class or just typing at the top level. Since you're so educated, I'll go have a margarita and let you consider this knowledge at length.

Nah, not really. Since you're the one learning here, that makes you the student. So instead, I recommend that you drink heavily, not me. See you when you're sober!

Previous: And then... / Next: Ruby Classes and Class Methods

Edit | Destroy | See All Posts

blog comments powered by Disqus