gpt4 book ai didi

ruby - 如何覆盖 Kernel.load

转载 作者:数据小太阳 更新时间:2023-10-29 07:00:59 25 4
gpt4 key购买 nike

我需要覆盖 Kernel.load为了观察和处理我们为监控而编写的一些 Ruby 文件。然而,它似乎不受此类恶作剧的影响。

很容易覆盖requirerequire_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

我满足于只覆盖 requirerequire_relative。不过,我很好奇 load 发生了什么。


事后思考:

看起来 load 不是由 requirerequire_relative 调用的。我认罪。抓得好Matt .

这个问题类似于“How to override require in Ruby?”。

良好的阅读:

Jörg's评论

I also want to give some love to Module#prepend, which would allow you to simply use super instead of that ugly alias_method stuff, with the additional bonus that your modifications would actually show up in the ancestry chain and thus much easier to debug.

非常明智,值得使用。

最佳答案

这里有两个简单的示例,它们似乎可以覆盖 requirerequire_relative,基于“When monkey patching a method, can you call the overridden method from the new implementation?”中的示例。

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 覆盖似乎工作得很干净。

关于ruby - 如何覆盖 Kernel.load,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31840181/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com