A word of warning:
This is heavy ruby abuse. It even got the Evil of the Day Award™ from zenspider.
Thou shalt not use alias_method_chain!
What it does
Chainable is an alternative to alias_method_chain, that uses inheritance, rather than aliasing. It does the following when “chaining” a method:
-
copy the original method to a new model
-
include the model
-
overwrite the method
Thus you can use super and keep your method list clean, too! It even supports a (rather dangerous) auto chaining mode, so you do not have to explicitly chain a method, but chain a method whenever it would be overwritten instead.
Example:
class Foo
def foo
10
end
# now chain to foo
chain_method :foo do
super + 3
end
# or turn on auto chaining
auto_chain do
def
10
end
def
super + 1
end
def
super ** 2
end
end
# or chain multiple methods at once
chain_method :foo, :bar do
super.to_s
end
end
f = Foo.new
puts f.foo # => 13
puts f. # => 121
Of course you can do this with any class (or module):
Array.class_eval do
chain_method :each
def each
return super if block_given? or RUBY_VERSION >= "1.8.7"
MyStuff::Enumerator.new self, :each
end
end
Note that there is a speed advantage when using chain_method without a block and doing a “def”, since chain_method will use define_method if a block is given, which produces slower methods (but makes the method a real closure).
Benchmark
chain_method tends do produce slightly faster methods than alias_method_chain:
user system total real
chainable (define_method) 0.160000 0.010000 0.170000 ( 0.183363)
chainable (def & eval) 0.170000 0.010000 0.180000 ( 0.177084)
alias_method_chain (define_method) 0.570000 0.030000 0.600000 ( 0.607330)
alias_method_chain (def & eval) 0.170000 0.020000 0.190000 ( 0.190048)
Installation
Add github gems, if you haven’t already:
gem sources -a http://gems.github.com
Install gem:
gem install rkh-chainable