Hi.
I’m trying to alias a method in a module and then overwriting this
method (still having access to the old method).
I tried the following code that does not seem to work with Ruby 1.9.2.
Do you have an idea why?
Thanks.
class A
def foo
puts ‘bar’
end
end
module Foo
def self.included(base)
base.class_eval do
alias_method :old_foo, :foo #unless method_defined?(:old_foo)
end
end
def foo
puts ‘foobar’
#old_foo
end
end
A.send :include, Foo
a = A.new
a.foo #=> bar
dagnan
January 29, 2011, 6:11am
2
:
I’m trying to alias a method in a module and then overwriting this method (still
having access to the old method).
try
class A
def foo
puts ‘bar’
end
end
module Foo
def self.included(base)
base.class_eval do
alias_method :old_foo, :foo #unless method_defined?(:old_foo)
end
end
def initialize(*args)
self.extend Foo::Overrider
end
module Overrider
def foo
puts ‘foobar’
#old_foo
end
end
end
A.send :include, Foo
a = A.new
a.foo #=> foobar
a.old_foo #=>bar
not just sure if that is the best way for modifying a class instance
methods. i’d rather just use require if possible …
best regards -botp
dagnan
January 29, 2011, 11:03am
3
Looks like when you include module Foo, the definition of foo in the
class still takes precedence over the one in the newly-included module.
This seems to work though:
class A
def foo
puts ‘bar’
end
end
module Foo
def self.included(base)
base.class_eval do
alias_method :old_foo, :foo
def foo
puts ‘foobar’
old_foo
end
end
end
end
A.send :include, Foo
a = A.new
a.foo
dagnan
January 31, 2011, 6:59pm
4
As of Ruby 1.9, when you include a module M in a class C, an anonymous
class is created and becomes the immediate superclass of C and subclass
of C’s original superclass. All instance methods of M will be inherited
by C in the same old way. So it is actually M#foo who gets overridden
(by its subclass C#foo); C#foo never gets redefined. This is how Ruby
currently resolves name conflicts raised during mixin.
If you call `super’ in C#foo, it will route to M#foo.
class A
def foo
puts ‘bar’
super
end
end
module Foo
def foo
puts ‘foobar’
end
end
A.send :include, Foo
a = A.new
a.foo # => bar\nfoobar
dagnan
January 31, 2011, 7:04pm
5
Su Zhang wrote in post #978699:
class A
def foo
puts ‘bar’
super
end
end
module Foo
def foo
puts ‘foobar’
end
end
A.send :include, Foo
a = A.new
a.foo # => bar\nfoobar
It’s the same in 1.8.7.
I think the OP was looking for a way to achieve the opposite behaviour:
to import a module which would override the method in the class.
dagnan
February 1, 2011, 4:34pm
6
Thank you all for your answers.
Remix and Prepend have not been updated since a few months. candlerb and
bot Pea solution are interesting.
dagnan
February 1, 2011, 2:22pm
7
On Mon, Jan 31, 2011 at 6:06 PM, Brian C. [email protected]
wrote:
I think the OP was looking for a way to achieve the opposite behaviour:
to import a module which would override the method in the class.
John M. (banisterfiend) has written some code to manipulate ancestor
chains, two of which are Remix and Prepend:
Remix: GitHub - banister/remix: Ruby modules re-mixed and remastered
Prepend: GitHub - banister/prepend: prepends modules in front of a class; so method lookup starts with the module
Prepend should do exactly what you’re looking for.