December 28, 2006
The Ruby send hack: how to gain access to an object's privates
I stumbled across an interesting Ruby hack that doesn't seem to be written down anywhere.
It turns out that private methods in Ruby aren't entirely private, and with a bit of indirection you can gain access to them as though they were public methods.
In Ruby 1.8 all we have to do is use the Object#send method.
To demonstrate:
class MyClass
private
def say_hello(name)
puts "Let's go back to my place, #{name}."
end
end
my_object = MyClass.new
So we get smacked if we try:
> my_object.say_hello Nomethoderror: private method `say_hello' called for #<MyClass:0x820b4> from (irb):8 from :0but instead:
> my_object.send :say_hello, "world" Let's go back to my place, world.
Touché!
Now, honestly, this strikes me as odd. Conceptually, I don't see why send should function differently from an ordinary method call with respect to access control.
The rubydoc for send says nothing of this, and there is some debate on the mailinglist as to whether Ruby 1.9's send will maintain this behavior.
But for now this can be very useful if you disagree with a class designer's method access choices.
Posted by Josh Staiger at 01:06 PM
Comments
Posted by: Bryce December 28, 2006 06:34 PM | Permanent link

Object#send works that way because there's no other way it can work – it can't really know if the caller is inside or outside the class, and too many useful features rely on that working.
You can also use instance_eval to voilate encapsulation like that: