Search code examples
rubysingletonmetaprogramming

Alias a method to a single object


I'm trying to define a singleton aliased method. As in:

name = 'Bob'
# I want something similar to this to work
name.define_singleton_method(:add_cuteness, :+)
name = name.add_cuteness 'by'

I'm sure I can pass a method object as a second parameter.

I wouldn't want to do it like this

name.define_singleton_method(:add_cuteness) { |val| self + val }

I want to alias the String#+ method not use it. Emphasis on alias, but sending the actual method object as a second parameter would be cool too.


Solution

  • Singleton methods are contained in that object's singleton class:

    class Object
      def define_singleton_alias(new_name, old_name)
        singleton_class.class_eval do
          alias_method new_name, old_name
        end
      end
    end
    
    rob = 'Rob'
    bob = 'Bob'
    bob.define_singleton_alias :add_cuteness, :+
    
    bob.add_cuteness 'by' # => "Bobby"
    rob.add_cuteness 'by' # => NoMethodError
    

    Object#define_singleton_method basically does something like this:

    def define_singleton_method(name, &block)
      singleton_class.class_eval do
        define_method name, &block
      end
    end