rubyguides

Kernel#__method__

__method__

Kernel#__method__ returns the name of the method in which it is called, as a Symbol. It is defined on Kernel, inherited by every object, and has been stable since Ruby 1.8.7.

It is the simplest answer to the question “what method am I in?” and shows up most often in logging, in method_missing handlers, and in code that forwards the current method name as data.

A typical logging use:

def calculate_total(cart)
  started_at = Time.now
  result = cart.sum { |item| item.price }
  warn "[#{__method__}] processed #{cart.size} items in #{Time.now - started_at}s"
  result
end

The interpolated #{__method__} becomes :calculate_total, so the log line tags itself without a manual string.

Signature at a glance

PropertyValue
Defined inKernel (private instance method)
Receiverignored; usually called with no explicit receiver
Argumentsnone
Return typeSymbol
Available sinceRuby 1.8.7
Statusnot deprecated

Calling it with arguments raises ArgumentError. Because it is private, the conventional call is just __method__, not obj.__method__.

Return value in a normal method

The symbol is the method’s name as it was defined, regardless of how the call was spelled.

def greet
  __method__
end

greet  # => :greet

__method__ does not care whether you used parens, a space, or a send. It always resolves to the lexical name of the enclosing method definition.

method versus callee

The interesting behaviour appears with alias_method and the alias keyword. The alias becomes a new entry point, but the body still belongs to the original method.

class Logger
  def write
    __method__
  end
  alias_method :emit, :write
end

Logger.new.emit  # => :write

__callee__ exists precisely for the entry point. Where __method__ resolves to the original method that defined the body, __callee__ resolves to whatever alias or original was actually invoked. Logging both gives you the implementation name and the call site without an extra argument.

class Box
  def store
    [:method, __method__, :callee, __callee__]
  end
  alias_method :put, :store
end

Box.new.put
# => [:method, :store, :callee, :put]

If your code dispatches on the call site (to pick a log level, a metric tag, or a branch), reach for __callee__. If you want the name of the code that is actually running, use __method__.

Inside blocks and at the top level

A block inherits __method__ from the method that defines it.

def ship_order(items)
  items.each { __method__ }
end

ship_order([1, 2, 3])
# => [:ship_order, :ship_order, :ship_order]

To get the name of the surrounding Proc or lambda itself, use Proc#name (Ruby 3.0+). At the top level there is no enclosing method, so __method__ returns nil. Code that interpolates the result into a log line should be ready for that, e.g. with to_s.

Two related traps:

  • Inside a block passed to define_method, __method__ returns the block’s own name, not the method being defined. Use caller_locations(1, 1).label to recover the dynamic name.
  • Inside method_missing, __method__ is always :method_missing. The missing name arrives as the name argument.
class Validator
  [:name, :email, :age].each do |attr|
    define_method("validate_#{attr}") do
      # __method__ here is the block's own name, not the dynamic one
      name = caller_locations(1, 1).label
      "validating via #{name} for #{attr}"
    end
  end
end

Validator.new.validate_email
# => "validating via validate_email for email"

The caller_locations(1, 1).label call reaches one frame up the stack to grab the method that is actually running.

Common pitfalls

  • Alias leakage. Dispatching on __method__ ignores the alias name. Use __callee__ or pass the name explicitly.
  • define_method trap. __method__ inside the block is not the defined method’s name.
  • Top-level returns nil rather than :main or any other symbol.
  • Stored procs and lambdas lose a meaningful __method__ once they leave their defining scope; use Proc#name or the binding.

See also