Christoph Petschnig Christoph Petschnig - 17 days ago 5
Ruby Question

Overwrite class method from another module

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
?

Answer

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.