Reputation: 1777
module Lab
def self.foo
puts 'foo from lab'
end
end
module M
def foo
puts 'foo from module'
super
end
end
module Lab
extend M
end
Lab.foo
I was expecting that I would see
foo from module
foo from lab
However what I am getting is
foo from lab
What I am trying to do is to intercept the value of a method from a gem and do something. I can use alias_method_chain but I am trying not to use that.
Upvotes: 2
Views: 88
Reputation: 65445
The methods defined on Lab
directly take precedence over the methods defined in modules such as M
that Lab
extends.
So the foo
defined directly on Lab
takes precedence over M#foo
, even though Lab.extend M
.
To get what you want, do this:
module Lab
module HasFoo
# foo isn't defined directly on Lab directly anymore;
# instead, it is defined in a separate module that
# Lab extends
def foo
puts "foo from lab"
end
end
extend HasFoo
end
module M
def foo
puts "foo from module"
super
end
end
module Lab
# when Lab extends another module with foo, that changes
# which concrete method the name foo gets resolved to
extend M
end
# now you should see the module foo and then the lab foo
Lab.foo
Upvotes: 1
Reputation: 6784
If you are expecting
foo from module
foo from lab
Then you need to put super in Lab#foo, like so:
module Lab
def self.foo
super
puts 'foo from lab'
end
end
module M
def foo
puts 'foo from module'
end
end
module Lab
extend M
end
Lab.foo
Upvotes: 1
Reputation: 168199
When you include/extend a module M
to a class C
, and call a method C#method
or C.method
that is also defined for M
, then C
has priority over M
in the search path of the method. In other words, you cannot overwrite a method by include/extend. You can only add new methods. See this related question.
In your case, Lab.foo
is simply called. The following (without Lab.foo
) will give you the desired result.
module M
def foo
puts 'foo from module'
end
end
module Lab
extend M
end
Lab.foo
# => foo from module
Note that your M
's superclass is Module
, and since Module#foo
is not defined, the following will cause an error.
module M
def foo
puts 'foo from module'
super
end
end
module Lab
extend M
end
Lab.foo
# => method undefined error
Upvotes: 0