我需要重写Kernel.load,以便监视和处理我们为监视而编写的一些Ruby文件。然而,这种诡计似乎是免疫的。
覆盖require和require_relative很容易,但是如果我没记错的话,load就位于它们下面,并限制了实际读取的文件。
下面是为什么它似乎受到保护而不被覆盖:
Kernel.module_eval do
alias_method :original_require, :require
def require(filename)
require_result = original_require(filename)
puts "required #{filename}"
require_result
end
alias_method :original_load, :load
def load(filename, wrap=true)
load_result = original_load(filename, wrap)
puts "loaded #{filename}"
load_result
end
end
include Kernel
require 'open-uri'
puts 'done'运行该输出:
required uri/rfc2396_parser
required uri/rfc3986_parser
required uri/common
required uri/common
required uri/generic
required uri/generic
required uri/ftp
required uri/generic
required uri/http
required uri/http
required uri/https
required uri/generic
required uri/ldap
required uri/ldap
required uri/ldaps
required uri/generic
required uri/mailto
required uri
required stringio
required date_core
required date
required time
required open-uri
done我满足于只覆盖require和require_relative。然而,我很好奇load是怎么回事。
后想:
看起来load不是由require或require_relative调用的。我认错了。抓得好哑光。
这个问题类似于"如何在Ruby中重写require?“。
读得好:
约格氏评论
我还想给Module#prepend一些爱,这将允许您只使用Super而不是那些丑陋的alias_method东西,还有额外的好处,您的修改实际上会出现在祖先链中,因此更容易调试。
是非常明智和值得使用的。
发布于 2015-08-06 20:42:35
下面是两个简单的示例,它们似乎适用于覆盖require和require_relative,它们基于"当猴子修补一个方法时,你能从新的实现中调用重写的方法吗?“中的示例。
module Kernel
old_require = method(:require)
define_method(:require) do |filename|
puts "require #{filename}"
old_require.call(filename)
end
old_require_relative = method(:require_relative)
define_method(:require_relative) do |filename|
puts "require_relative #{filename}"
old_require_relative.call(filename)
end
end或
module KernelExtensions
def require(filename)
puts "require #{filename}"
super
end
def require_relative(filename)
puts "require_relative #{filename}"
super
end
end
class Object
prepend KernelExtensions
end运行第二个使用
module Kernel
prepend KernelExtensions
end没有工作,但由于Object包含内核,使用class Object覆盖似乎工作得很干净。
https://stackoverflow.com/questions/31840181
复制相似问题