Explicit Methods Vs. Aliasing
It’s a fairly common practice in ruby to add aliases for methods, so that the same method can be referred to by two different names. It’s so common that ruby has a keyword for this, so to if you have a method such as:
def one
[]
end
And you want uno to call the same method, you just do the following:
alias uno one
Note that you use a literal name when aliasing, so the alias keyword can only alias methods whose names can be literals. Also note that you don’t separate the the two method names with a comma, as it isn’t a regular method call.
If you define a method with a name that is not a valid literal, such as:
define_method(:"eleventy-one") do
111
end
And you want to alias it to “cent onze”, you need to use alias_method:
alias_method :"cent onze", :"eleventy-one"
alias_method is not a keyword, it’s a private instance method of the Module class, so it uses regular method call syntax, where the arguments are separated with commas. Unlike alias, alias_method takes symbols instead of literals, so it can be used to alias methods whose names aren’t valid literals.
Note that aliasing methods is not the same as creating one method that calls the other method. When you do:
alias uno one
it does not do:
def uno
one
end
instead, it does:
def uno
[]
end
Basically, an alias adds a new method that uses the same method body as the method being aliased. Now most of the time, that is what you want. However, when creating subclass hierarchies, sometimes it is what you want, and sometimes it isn’t. Think about this code:
class A
def position
1
end
alias positie position
end
class B < A
def position
2
end
end
Basically, you have a class hierarchy, with two separate names for a method. In lower levels of the class hierarchy, you override the method to give the class specific behavior. Unfortunately, this doesn’t work well:
a = A.new
b = B.new
a.position # => 1
b.position # => 2
a.positie # => 1
b.positie # => 1 !!!
Note the incorrect result for b.positie. This is because B#positie is not defined in B, so it calls A#positie, using ruby’s usual method lookup. Unfortunately, because you used alias, what you really did is this:
class A
def positie
1
end
end
Which is why b.positie gives you 1. The correct solution in this case is not to use method aliasing, but to create actual methods that call the methods they are supposed to alias:
class A
def position
1
end
def positie
position
end
end
class B < A
def position
2
end
end
This gives you correct results:
a.position # => 1
b.position # => 2
a.positie # => 1
b.positie # => 2
Now, that does not mean that using explicit methods is better than aliasing in all cases, you need to use your judgment and make a decision on a case by case basis. If you have methods a and b, and they are always supposed to mean the same thing, an explicit method is probably better. However, if you have methods c and d, which happen to do the same thing, but are not required to do so, then an alias is probably better.
So what does this have to do with Sequel? Well, I recently made some modifications to Sequel to use explicit methods over aliasing in cases where it makes sense.