Yngve Hammersland Yngve Hammersland - 1 year ago 67
Ruby Question

How to access a (shadowed) global function in ruby

I was wondering how to access a global function

fn
in ruby from a class which also defined a method
fn
. I have made a workaround by aliasing the function like so:


def fn
end

class Bar
alias global_fn fn
def fn
# how to access the global fn here without the alias
global_fn
end
end


I'm looking for something along the lines of c++'s :: to access global scope but I can't seem to locate any information about it. I guess I don't know specifically what I'm looking for.

Answer Source

At the top-level a def adds a private method to Object.

I can think of three ways to get the top-level function:

(1) Use send to invoke the private method on Object itself (only works if the method is not a mutator since Object will be the receiver)

Object.send(:fn)

(2) Get a Method instance of the top-level method and bind it to the instance you want to invoke it on:

class Bar
  def fn
    Object.instance_method(:fn).bind(self).call
  end
end

(3) Use super (assumes no super classes of Bar below Object redefine the function)

class Bar
  def fn
    super
  end
end

UPDATE:

Since solution (2) is the preferable one (in my opinion) we can try to improve the syntax by defining a utility method on Object called super_method:

class Object
  def super_method(base, meth, *args, &block)
    if !self.kind_of?(base) 
      raise ArgumentError, "#{base} is not a superclass of #{self}" 
    end

    base.instance_method(meth).bind(self).call(*args, &block)
  end
end

Use like the following:

class Bar
  def fn
    super_method Object, :fn
  end
end

Where the first argument to super_method must be a valid superclass of Bar, the second argument the method you want to invoke, and all remaining arguments (if any) are passed along as parameters to the selected method.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download