Reputation: 4157
I want to modify the existing module A
from a library:
module A
class << self
def foo
bar('Baz')
end
private
def bar(val)
val.upcase
end
end
end
A.foo
=> "BAZ"
module B
extend A
def self.bar(val)
val.downcase
end
end
B.foo # hoping for 'baz', but instead:
NoMethodError: undefined method `foo' for B:Module
Is there a way to re-use method .foo
from A
and only modify method .bar
?
Upvotes: 1
Views: 208
Reputation: 86
extend A
doesn't work, because foo
and bar
are no instance methods of A
, but of A
's singleton class. To re-use those methods, you have to either create a copy of A
as mudasobwa described, or you can use a refinement of A
's singleton class like this:
module B
extend(refine(A.singleton_class) do
def bar(val)
val.downcase
end
end)
end
B.foo # => "baz"
You cannot use extend A.singleton_class
as extend
doesn't accept a class as argument. refine
returns a module which is exactly what's needed.
Upvotes: 4
Reputation: 121010
Assuming you have A
declared as above, the following code would do:
▶ B = A.clone
#⇒ B
▶ (class << B; self; end).send :define_method, :bar do |val|
val.downcase
end
▶ A.foo
#⇒ "BAZ"
▶ B.foo
#⇒ "baz"
There probably should be less tricky way, but I can’t yet figure it out.
Upvotes: 2