rubyalias-method

Is there an alias_method for a class method?


Consider the following class:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
end

This is no issue and you can call Foo.new.a_new_inst_method with no issue.

I'd like the ability to have a class method like Foo.add_widget(*items) and alias it so I can do something like:

Foo.add_widget 'item1'
Foo.add_widgets 'item2', 'item3'

So essentially it has a "ruby style" like 1.minute and 2.minutes so I want to alias a Foo.add_widget so calling Foo.add_widgets calls the exact same method. I know I could wrap it but I feel like I should be able to do this in a cleaner fashion.

Consider my attempt at trying something like this:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
  alias_method :a_new_class_method, :a_class_method
end

However, I get the following error:

NameError (undefined method `a_class_method' for class `Foo')

And so it looks like this doesn't work for class methods. How do I go about doing this?


Solution

  • alias_method aliases an instances method of the receiver. Class methods are actually instance methods defined on the singleton class of a class.

    class MyClass
      def self.a
        "Hello World!"
      end
    end
    
    method_1 = MyClass.method(:a).unbind
    method_2 = MyClass.singleton_class.instance_method(:a)
    
    method_1 == method_2
    #=> true
    

    To alias an instance method defined on the singleton class you can either open it up using the class << object syntax.

    class << MyClass
      alias_method :b, :a
    end
    
    MyClass.b
    #=> "Hello World!"
    

    Or you can refer to it directly using the singleton_class method.

    MyClass.singleton_class.alias_method :c, :a
    
    MyClass.c
    #=> "Hello World!"
    

    If you are still within the class context self will refer to the class. So the above could also be written as:

    class MyClass
      class << self
        def a
          "Hello World!"
        end
        alias_method :b, :a
      end
    end
    

    Or

    class MyClass
      def self.a
        "Hello World!"
      end
      singleton_class.alias_method :c, :a
    end
    

    Or a combination of the two.