Daniel Rench

Web application development : Servers : Networks : E-Mail : DNS : Databases : Programming for hire

previous : contact : linkedin : code : links : pictures : facebook : twitter : next

Transmutable (?) Objects in Perl and Ruby

I have no idea if "transmutable" is the right word to describe this concept but I'm using it anyway.

In Perl, I sometimes find it useful to "transmute" objects. For example:

sub Grape::new {
	my $class = shift;
	bless {}, $class;
}

sub Grape::dehydrate {
	my $self = shift;
	bless $self, 'Raisin';
}

sub Raisin::new {
	my $class = shift;
	bless {}, $class;
}

my $x = Grape->new();
print ref($x), "\n"; # prints "Grape"
$x->dehydrate();     # it's not a Grape anymore
print ref($x), "\n"; # prints "Raisin"
$x->dehydrate();     # Raisin doesn't have a dehydrate() method, so it dies

To do this in Ruby, I first tried something like this:

class Grape
	def dehydrate
		self = Raisin.new
	end
end

But Ruby complains "Can't change the value of self". I ended up trying something with Ruby's version of AUTOLOAD, method_missing:

class Grape
	def initialize
		@me = Hidden::Grape.new
	end
	def method_missing(method, *args)
		r = @me.method(method).call(*args)
		@me = r if /^Hidden::/.match(r.class.to_s)
		return r
	end
	def class
		@me.class.to_s.sub(/^Hidden::/, '')
	end
	def methods
		@me.methods
	end
end

module Hidden
	class Grape
		def dehydrate
			Raisin.new
		end
	end
	class Raisin
	end
end

x = Grape.new
puts(x.class) # prints "Grape"
x.dehydrate
puts(x.class) # prints "Raisin"
x.dehydrate   # NameError: undefined method `dehydrate' for class `Hidden::Raisin'

Various things seem wrong about it (especially overriding class() and methods()), but it pretty much does what I want.

11/15/2006 update: I no longer think the above seems "wrong". If anything it's probably considered insufficiently weird in Ruby circles.

<< The Cookie Hack: using mod_perl to make IE7 think you're not using Basic Auth (even though you are) | Home | Portfolio | Contact | arguments.callee: A dren.ch Endorsement >>