A method alias can make sense or even can be necessary for various reasons:
- Enable a class for duck typing
- Increasing an inherited methods meaning/ readability
- Extend an inherited methods behavior (in the sense of aspect oriented programming)
That can be achieved in Ruby in different ways, e. g. with Module#alias_method.
At first the Company model as an example:
rail$ rails g model Company name:string && rake db:migrate
and the corresponding model with an alias label on the attribute method name:
class Company < ActiveRecord::Base
alias_method :label, :name
end
Unfortunately that does not work:
Company.new # => NameError: undefined method `name' for class 'Company'
The reason is quite simple. Ruby on Rails creates attribute accessors dynamically and therefore helps itself with the method missing approach. But at the time of class instantiation the accessors are not created yet. However when alias_method tries to make a copy of the original method, it consequentially fails with NameError.
The solution is Module#alias_attribute. Ruby on Rails extended Module and enables aliasing in ActiveRecord. The principle is simple. A new method is created by meta programming, which inernally calls the original method.
Thus the model has to look like:
class Company < ActiveRecord::Base
alias_attribute :label, :name
end
and then:
company = Company.new(name: 'Google')
company.name # => "Google"
company.to_s # => "Google"
Furthermore alias_attribute generates the appropriate setter methods:
company = Company.new(name: 'Google')
company.label = 'Apple'
company.name # => "Apple"
company.label # => "Apple"
Since the alias_attribute is glued to Module, it works for each class:
class Article
attr_accessor :name
alias_attribute :title, :name
def initialize name
@name = name
end
end
Article offers two more methods title and title=:
article = Article.new 'Aliasing the Rails way'
article.title # => "Aliasing the Rails way"
article.title = 'ActiveRecord attribute aliasing.'
article.title # => "ActiveRecord attribute aliasing."
article.name # => "ActiveRecord attribute aliasing."