Ruby 1.8.5 *_eval Methods are subject to access modifiers on self!


Sep 28, 2007
Since we're running CentOS5 on our svn/CC.rb server. There are no packages for Ruby 1.8.6, so naturally, I just went with the v1.8.5 install. Everything was working great, until I came across this gotcha. Since I can't seem to find anything documented anywhere, hopefully other people will be able to find this article, when they google for it.

In ruby 1.8.5, self, in an instance_eval block, is subject to the same access modifiers as any old instance variable. Protected, and private methods raise "NoMethodError: protected/private method `x' called for ...". Luckily, though, the send(:method_name) hack still works to get around any access modifier. So, if you need to get your code running on 1.8.5, that's the workaround.
class Person
  protected
    def something_secret
      "don't tell anybody"
    end
  
  private
    def something_really_secret
      "REALLY don't tell anybody"
    end
end
  
## Ruby 1.8.5

person.instance_eval { self.something_secret } # NoMethodError: protected method `something_secret' called for ...

person.instance_eval { self.something_really_secret } # NoMethodError: protected method `something_really_secret' called for ...

person.send :something_secret # "don't tell anybody"
person.send :something_really_secret # "REALLY don't tell anybody"

## Ruby 1.8.6

person.instance_eval { self.something_secret } # "don't tell anybody"
person.instance_eval { self.something_really_secret } # "REALLY don't tell anybody"

person.send :something_secret # "don't tell anybody"
person.send :something_really_secret # "REALLY don't tell anybody"