skip to content

In Ruby, how do the alias keyword and Module#alias_method differ, and when do you need alias_method instead of alias?

level: middleimportance: should knowfreq 52%

answer

  1. keyword vs method call
  2. lexical class vs self
  3. globals only with alias
  4. returns the new name since 3.0
  5. Style/Alias picks one

basics

~20 s

alias is a keyword taking bare names and aliasing in the lexically enclosing class; it also aliases globals. alias_method is a Module method taking Symbol or String arguments, acting on self at runtime and returning the new name.

solid answer

~40 s

`alias new old` is a **keyword**: its operands are bare names or symbol literals with no comma, and it defines the alias in the class **lexically enclosing** the code, even when written inside a method. It can also alias global variables (`alias $new $old`). `alias_method :new, :old` is a **public method of `Module`**: its arguments are ordinary expressions (Symbols or Strings, from variables if you like), it acts on **`self`**, the receiver at runtime, and since Ruby 3.0 it returns the new name as a Symbol. Both copy the original method's current body, so later redefinition of the original does not change the alias. You need `alias_method` inside a class-level method that subclasses call, or when you want its return value, as in `private alias_method :old_label, :label`.

code

ruby · 12 lines
ruby
class Temperature
  def label = "#{@celsius} C"

  alias summary label                     # keyword, bare names
  private alias_method :legacy_label, :label  # returns :legacy_label

  def label = "#{@celsius} degrees C"     # summary keeps the old body
end

$log_level = :info
alias $level $log_level                  # globals: keyword only
$level                                   # => :info

go deeper

for a junior

Recall the two spellings, alias new old with bare names and alias_method :new, :old with symbols and a comma, and that both create a second name.

for a middle

Explain the lexical-class versus self difference, the copied body, global-variable aliasing, and the Symbol return since 3.0.

for a senior

Choose alias_method in class-level helpers and macros that subclasses call, and pick a Style/Alias setting so a codebase does not mix the two without reason.

for a principal

Decide whether aliasing belongs in a public API at all, weighing discoverable alternative names against the maintenance cost of two names for one behaviour.

## Two ways to give a method a second name An **alias** is a second name for an existing method. Ruby offers two tools that both create one, and interviews probe the differences: | | `alias` keyword | `Module#alias_method` | |---|---|---| | Kind | language keyword | public method on `Module` | | Syntax | `alias label to_s` or `alias :label :to_s` (no comma) | `alias_method :label, :to_s` | | Arguments | bare names or symbol literals in the source | any expressions giving Symbols or Strings | | Target class | the class lexically enclosing the code | `self`, the receiver at runtime | | Global variables | `alias $new $old` works | not supported | | Return value | not meant to be used | the new name as a Symbol (3.0+) | ## Lexical class versus self The difference that changes behaviour is **where the alias lands** when the code runs inside a method: ```ruby class Temperature def to_s = "#{@celsius} C" def self.alias_with_keyword alias describe to_s # always on Temperature end def self.alias_with_method(name) alias_method name, :to_s # on self, whoever calls end end class Reading < Temperature def to_s = "reading #{@celsius}" end Reading.alias_with_keyword Reading.alias_with_method(:summary) Temperature.method_defined?(:describe) # => true Reading.instance_method(:summary).owner # => Reading ``` - `alias` resolved `to_s` and placed `describe` in `Temperature`, the class whose body contains the code, even though `Reading` called the method. `Reading.new.describe` therefore runs `Temperature`'s `to_s` body. - `alias_method` ran with `self` set to `Reading`, so `summary` is defined on `Reading` and copies `Reading#to_s`. This is why class-level helpers that subclasses call should use `alias_method`. ## Behaviour both share 1. **The body is copied at alias time.** Redefining `to_s` afterwards leaves `describe` running the old body. Patterns that wrap an existing method build on this. 2. **The alias is an independent method entry.** Removing or redefining one name does not affect the other. 3. **A missing original raises `NameError`** at the point the alias is made. 4. **Inherited methods can be aliased.** Aliasing a parent's method in a child defines the new name on the child. ## Return value and one-line visibility Before Ruby 3.0, `alias_method` returned the module itself. Since 3.0 it returns the **new name as a Symbol**, so it composes with methods that take a name, for example `private alias_method :legacy_label, :to_s`. Treat the keyword `alias` as a statement and do not rely on its value. ## Names as arguments Because `alias_method` is an ordinary method, its arguments are evaluated like any others: - Symbols and Strings are both accepted: `alias_method "label", "to_s"` works. - Names can come from variables, loops or method parameters, which suits class-level helpers that generate several aliases. - The call can be made from outside the class body, `Temperature.alias_method(:label, :to_s)`, since the method has been public since Ruby 2.5. The keyword takes names written in the source. It accepts bare identifiers or symbol literals, and RuboCop's default style asks for the bare form, `alias label to_s`, over `alias :label :to_s`. ## Picking one in a codebase RuboCop's `Style/Alias` cop enforces a single style: - `EnforcedStyle: prefer_alias` is the default in RuboCop 1.91: use `alias new old` with bare names where the keyword works. - `prefer_alias_method` requires `alias_method` everywhere; the cop's configuration lists it as the preview default expected in the next major release. - Either way, the cop demands `alias_method` when the code sits inside a method definition or a block (other than `instance_eval`), exactly because of the lexical-versus-`self` difference. ## Key points - `alias`: keyword, bare names, lexical class, global variables too. - `alias_method`: method call, Symbol or String arguments, runtime `self`, returns a Symbol since 3.0. - Both snapshot the current body, and both raise `NameError` for a missing original.

  • In Ruby, after `alias summary label`, what does `summary` run if `label` is redefined later in the class?
    It still runs the original body. An alias copies the method as it exists when the alias is made, so the two names become independent entries. Redefining `label` replaces only `label`; `summary` keeps the old behaviour, which is also true for `alias_method`.
  • Why does `private alias_method :legacy_label, :label` work as one line on Ruby 4.0 but not on Ruby 2.7?
    Since Ruby 3.0, `alias_method` returns the new name as a Symbol, which `private` accepts. On 2.7 it returned the module itself, so `private` received a class instead of a method name and raised `TypeError` ("... is not a symbol nor a string").

saying these in an interview costs you the question

  • alias and alias_method are identical; the choice is only style.
  • alias inside a class method defines the alias on the subclass that calls it.
  • An alias follows the original, so redefining the original changes the alias too.
  • alias_method can alias global variables like $stdout.
  • alias_method still returns the class, so it cannot be wrapped in private.