Tropical Software Observations

24 August 2006

Posted by Bacchus D

at 4:44 AM



Object Creation In Ruby

Please bear with me as I stumble through 'Programming Ruby'. Today's topic is object creation.

Here's a very simple Ruby class. Its three attributes are all initialized in the constructor, aptly named initialize(). Each attribute has a public accessor and mutator granted by the attr_reader and attr_writer keywords, respectively. It's worth pointing out here that methods are public by default, though access can be tightly controlled as I'll show later.

class Song

attr_reader :name, :artist, :duration
attr_writer :name, :artist, :duration

def initialize(name, artist, duration)
@name = name
@artist = artist
@duration = duration

def to_s # instance method
"#{@artist} - #{@name} (#{@duration})"

def self.clone(s) # class method
newSong =, s.artist, s.duration)
return newSong


Creating an instance of this class is simple:

s1 ="All Things To All Men", "Cinematic Orchestra", 290)

However, the following invocation results in a "private method `initialize' called for #Song:0x100f3f88 (NoMethodError)" error:

s2 = s1.initialize("Seeing Red", "Minor Threat", 125)

There are a couple of interesting things to note here. First off, even though we didn't scope initialize() as private, apparently it is anyway. More interesting, though, is that we instantiate objects using the class method new() provided in the base class Object and not through the use of a global operator as in languages like C++. While initialize() plays an important role in object creation, it doesn't tell the whole story. The class method allocates memory for a new, uninitialized object. It then invokes the new object's initialize() method, passing along the arguments from the original call to new(). In contrast to languages like Java that treat memory allocation and initialization of objects atomically, Ruby allows the programmer to handle these operations discretely by overriding It might help to think of new() as a built-in factory method inherited from the base class. Here's a pared down version of our Song class that illustrates how you might use this strategy to limit object creation by performing lookups against a cache.

class Song

attr_reader :name, :artist, :duration

def initialize name, artist, duration
@name = name
@artist = artist
@duration = duration

def *args
# check cache first
obj = CacheManager.lookup args[0]

# if cache miss, then create new song
if obj == nil
newObj = self.allocate
newObj.send :initialize, *args
return newObj

# we have a hit, just return it


Minus the cache bit this example was basically lifted straight out of Programming Ruby. Instead of blindly creating an object every time gets called, we first check the cache to see if an object with the same key already exists. If so we simply return the cache hit, otherwise we reimplement, allocating memory for a generic object, then invoking Song#initialize() by passing its symbol to Song#send() (once again inherited from base class Object).


Thomas, D. and Hunt, A. "Programming in Ruby." Dr. Dobb's Journal. 2001.

"Ruby 1.8.4 Documentation." 2006.

Thomas, Dave. Programming Ruby. 2005. The Pragmatic Bookshelf.


dreamcat4 said...

Hi, I get the following error:

/Users/id/tmp/yamldoc/lib/class_attributes.rb:115:in `new': uninitialized constant CacheManager (NameError)

There isn't any reference to "Cache Manager" or "CacheManager" in the ruby documentation. So where CacheManager is? Unofficial / private class?