I need to override Kernel.load
in order to watch and process some Ruby files we've written for monitoring. However, it seems immune to such shenanigans.
It's easy to override require
and require_relative
, but load
sits under them and bottlenecks the actual file read if I remember right.
Here's why it seems to be protected from overriding:
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'
Running that outputs:
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
I'm content to only override require
and require_relative
. However, I'm curious what's going on with load
.
Afterthoughts:
It looks like load
isn't called by require
or require_relative
. Mea culpa. Good catch Matt.
This question is similar to "How to override require in Ruby?".
Good reading:
- "Ways to load code"
- "Ruby Require VS Load VS Include VS Extend"
- And Jörg's amazing answer in "When monkey patching a method, can you call the overridden method from the new implementation?"
Jörg's comment
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.
is very sensible and worth using.