How to Alias a Class Method in Rails Model

Is there an alias_method for a class method?

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.

How to alias a class method within a module?

You could use define_singleton_method to wrap your old method under a new name, like so:

module MyModule
def alias_class_method(new_name, old_name)
define_singleton_method(new_name) { old_name }
end
end

class MyClass
def my_method
puts "my method"
end
end

MyClass.extend(MyModule)
MyClass.alias_class_method(:my_new_method, :my_method)
MyClass.my_new_method # => "my method"

Answering your comment, you wouldn't have to extend every single class by hand. The define_singleton_method is implemented in the Object class. So you could simply extend the Object class, so every class should have the method available...

Object.extend(MyModule)

Put this in an initializer in your Rails app and you should be good to go...

Alias a method to a single object

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

Is there simpler (one-line) syntax to alias one class method?

Since Ruby 1.9 you can use the singleton_class method to access the singleton object of a class. This way you can also access the alias_method method. The method itself is private so you need to invoke it with send. Here is your one liner:

singleton_class.send(:alias_method, :generate, :new)

Keep in mind though, that alias will not work here.

How can I dynamically define an alias method for a class method?

So just learned that this will do the trick:

module Calculator
def memoize
define_singleton_method(name, method(name))
end
end

Then when Calculator gets included in Product it will define the singleton method as I needed. I still don't know why alias_method needs to only work on instance methods.. and I don't know why class_eval or instance_eval didn't solve the problem.. but at least I have a solution..

How to include a module in a model class with alias?

Modules are not classes and thus cannot use classical hierarchical inheritance. However a module can include other modules - which means you can use paralell inheritance.

module Name
extend ActiveSupport::Concern

included do
field :name, type: String
end

def greeting(name)
p "hello #{name}!"
end
end

module Nickname
extend ActiveSupport::Concern

include Name

included do
field :nickname, type: String
end

# if you named this method greeting it would
# overwrite the implementation from the Name module
def friendly_greeting(name)
p "hello #{name}! You can call me #{nickname}"
end
end

class Foo
include Name
end

class Bar
include Nickname
end

Foo.new.name # nil
Foo.new.nickname # NoMethodError

Foo.fields.keys # ['_id', 'name']
Bar.fields.keys # ['_id', 'name', 'nickname']

Foo.new(name: 'Max').greeting # "hello Max!"
Foo.new(name: 'Max').friendly_greeting # NoMethodError

bar = Bar.new(name: 'Richard', nickname: 'Dick')
bar.greeting # "hello Richard!"
bar.friendly_greeting # "hello Richard! You can call me Dick"

alias for chain methods in rails

class User < ApplicationRecord
belongs_to :mother, class_name: "User", optional: true
belongs_to :father, class_name: "User", optional: true
has_one :grandfather, through: :father, source: :father
has_one :grandmother, through: :father, source: :mother
end


Related Topics



Leave a reply



Submit