Super Snakes

Have you ever been confused by the __underscores__ required by some of __RUBY__'s features? You can get it right with this overview of all of "super snake" keywords and methods.

There are three different types of underscore-wrapped syntaxes in the Ruby core language:

Let us take a look at each of them, and understand the motivations behind. Or directly jump to:


Keywords (Built into Ruby Syntax)

These are directly translated by the Ruby interpreter: You cannot use meta-programming with these, since they will always return the corresponding value directly:


Returns the current source file's name. Might be special value for unusual invocations:

Context Value
File, directly executed path name, can be relative
File, required / loaded absolute path
IRB "(irb)"
eval'd "(eval)"
$ ruby -e "-e"
Standard Input "-"


Returns the line number in the current source file. Also works in IRB and with code executed with $ ruby -e, STDIN or eval.


Returns the source file's encoding, as specified per magic comment. The default source file encoding is UTF-8. The important thing to understand is that this value should correspond to the actual encoding of the source file, so to change the source encoding, it is not enough to just change the magic comment, you will also need to convert the source file.

You should also note that this is unrelated to some other global encoding configurations, which serve different purposes:

__END__ (at beginning of line)

A special syntax which will end the source file earlier and create big data.

Underscore-Wrapped Kernel Methods

These special Kernel methods are lowercased to highlight the fact that they are actually just methods and no built-in keywords.

__method__ and __callee__

Both return the current method's name, but they differ in a detail: When using a method alias, __callee__ will return the aliased method name, while __method__ would return the original name:

def example!
  p [__method__, __callee__]
alias test! example!

example! # => [:example!, :example!]
test! # => [:example!, :test!]

Two similar and useful methods are Kernel#caller and Kernel#caller_locations, which provide some more context.


Returns File.dirname(File.realpath(__FILE__)), which is the absolute path of the directory of the current source file.

While it also works in IRB, it will return nil in eval, $ ruby -e, and STDIN contexts.

Underscore-Wrapped BasicObject Methods

Both of the following methods are so important that every object (even those that inherit from BasicObject directly) should have. This is why they got some underscore companions.


Returns the object id, just like Object#object_id. It mainly exists for historical reasons, most people use object_id nowadays.


The __send__ method is an alias of the Object#send, which dynamically calls the method given as a symbol argument. Its purpose is that you should still be able to use the send functionality in case someone redefines the send method. The interpreter will issue a warning¹ should you try to redefine or remove it:

warning: redefining `__send__' may cause serious problems

Nevertheless, it is probably not a good idea either to redefine non-underscore-wrapped send, since a lot of meta-programming relies on it…

¹ This is not true for __id__ - Ruby will not complain if you choose to redefine it. It will complain for object_id though.

Also See

Many thanks to Shannon Skipper for pointing out that the mysterious SUPPORT_JOKE compiler option's __goto__ and __label__ also make use of underscores

More Idiosyncratic Ruby