https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112012-12-12T17:23:09ZRuby Issue Tracking SystemRuby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=346512012-12-12T17:23:09ZAnonymous
<ul></ul><p>Is there a particular benefit of this over the current setup of require?<br>
require() calls are not async so I don't really see the benefit of<br>
adding callbacks to them.</p>
<p>You mentioned you wanted to use it for monitoring, perhaps you can<br>
further explain that to clarify what you're trying to get at.</p>
<p>Yorick</p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=347092012-12-14T00:43:03Ztrans (Thomas Sawyer)
<ul></ul><p>=begin<br>
There are have been times when I wanted to see what libraries were being loaded and in what order. Usually because of some esoteric bug, and trying to isolate what libraries are involved. In such a case I've had to manually override load and require, something like:</p>
<p>class << Kernel<br>
alias :_require, :require<br>
def require(*args)<br>
$stderr.puts "require: %s" % [args.inspect]<br>
_require(*args)<br>
end</p>
<pre><code>alias :_load, :load
def load(*args)
$stderr.puts "load: %s" % [args.inspect]
_load(*args)
end
</code></pre>
<p>end</p>
<p>module Kernel<br>
def require(*args)<br>
Kernel.require(*args)<br>
end<br>
def load(*args)<br>
Kernel.load(*args)<br>
end<br>
end</p>
<p>Notice we have to do both Kernel instance and singleton methods to be sure we catch all of them. These days we might also need to add (({#require_relative})) to that.</p>
<p>So the thought then is, if there were callbacks, it would be easier to do, simply:</p>
<p>def required(*args)<br>
$stderr.puts "require: %s" % [args.inspect]<br>
end</p>
<p>def loaded(*args)<br>
$stderr.puts "load: %s" % [args.inspect]<br>
end</p>
<p>Actually considering this a bit more, it would probably be even better just to have one callback method that passed options to designate which kind of loading took place. e.g.</p>
<p>def loaded(file, opts)<br>
opts[:load] => true means #load was used/<br>
false means #require was used</p>
<pre><code>opts[:relative] => true means #require_relative was used
opts[:wrap] => the wrap argument for #load.
</code></pre>
<p>end</p>
<p>=end</p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=347782012-12-17T01:28:07Ztrans (Thomas Sawyer)
<ul></ul><p>=begin<br>
Some additional thoughts on this. It occurs to me that #prepend would make this a ((<em>little</em>)) easier now. One could do:</p>
<p>module LoadCallbacks<br>
def load(*args)<br>
super(*args)<br>
$stderr.puts "load: %s" % [args.inspect]<br>
end</p>
<pre><code>def require(*args)
super(*args)
$stderr.puts "require: %s" % [args.inspect]
end
def require_relative(*args)
super(*args)
$stderr.puts "require: %s" % [args.inspect]
end
</code></pre>
<p>end</p>
<p>module Kernel<br>
prepend LoadCallbacks<br>
class << self<br>
prepend LoadCallbacks<br>
end<br>
end</p>
<p>That's a little more elegant, but still feels a bit clunky.</p>
<p>I think what would really make the difference, and what would make this callback feature request effectively pointless, is if Ruby had a single method through which all loading was routed. So (({#load})), (({#require})) and (({#require_relative})) would all call this one method passing in options (i.e. named parameters) to tell it which kind of loading is to happen. That would be nice b/c it would allow us a single target method to see what was going on, instead of the current ((<em>six</em>)) methods!<br>
=end</p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=347792012-12-17T02:49:59ZAnonymous
<ul></ul><p>It seems that you are shaping and changing your suggestion with each new post,<br>
so it is a bit hard to react. But the way I see it, your suggestions belong<br>
somewhere to Std-lib 'debug'. Perhaps it might be possible to change stdlib<br>
'debug' to support cherrypicking like ActiveSupport, so you could call<br>
require 'debug/kernel/load_callbacks' if you want those callbacks, but not the<br>
DEBUGGER itself. I am against adding this directly to the core.</p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=347892012-12-17T13:42:25Ztrans (Thomas Sawyer)
<ul></ul><blockquote>
<p>It seems that you are shaping and changing your suggestion with each new post,<br>
so it is a bit hard to react.</p>
</blockquote>
<p>Sorry. It's a process and discussion sort of request, which is why I presented it first with a question.</p>
<blockquote>
<p>But the way I see it, your suggestions belong somewhere to Std-lib 'debug'.<br>
Perhaps it might be possible to change stdlib 'debug' to support<br>
cherrypicking like ActiveSupport,</p>
</blockquote>
<p>You mean "cherrypicking like Facets" right? ;)</p>
<blockquote>
<p>so you could call require 'debug/kernel/load_callbacks' if you want those callbacks,<br>
but not the DEBUGGER itself. I am against adding this directly to the core.</p>
</blockquote>
<p>I think that's very reasonable. Ultimately I like my last suggestion, the one about having a central method that handles loading. That strikes me as a more solid design for Ruby in general. So I think I will make a more concrete proposal for that in another ticket. But short of that, then I agree. Having a standard "cherrypickable" debugging library for this would be the nicest approach.</p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=348192012-12-18T13:57:18Ztrans (Thomas Sawyer)
<ul></ul><p>=begin<br>
Ran into a little snag with implementation of this as a simple Ruby library. It is not possible to override (({#require_relative})) to add the callback b/c it is lexically scoped (is that the right term for this?). In other words, (({#require_relative})) uses the (({<strong>FILE</strong>})) in which it is called. But any override ends up with the (({<strong>FILE</strong>})) in which the override is defined instead.</p>
<p>Is there a way around this? If not, then the only way to do this properly/completely is via core code.<br>
=end</p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=348202012-12-18T13:58:42ZAnonymous
<ul></ul><p>=begin<br>
You can use (({Kernel#caller})) to obtain the filename of the caller<br>
=end</p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=348312012-12-18T23:43:03Ztrans (Thomas Sawyer)
<ul></ul><p>=begin<br>
@charliesome That doesn't quite fix the problem.</p>
<a name="foorequire_relativerb"></a>
<h1 >foo/require_relative.rb<a href="#foorequire_relativerb" class="wiki-anchor">¶</a></h1>
<p>alias_method :require_relative_without_callback, :require_relative</p>
<p>def require_relative(feature)<br>
result = require_relative_without_callback(feature)<br>
Kernel.loaded(feature) if result<br>
result<br>
end</p>
<a name="baruse_itrb"></a>
<h1 >bar/use_it.rb<a href="#baruse_itrb" class="wiki-anchor">¶</a></h1>
<p>load 'foo/require_relative.rb'<br>
require_relative "anything"</p>
<p>Produces</p>
<p>LoadError: cannot load such file -- foo/anything</p>
<p>But it should be (({bar/anything})).</p>
<p>Your suggestion would allow me to <em>re-implement</em> #relative_require. I know how to do that, I've done it before for Facets. But I've never felt it a very robust solution.<br>
=end</p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=349192012-12-21T05:37:23ZAnonymous
<ul></ul><p>trans (Thomas Sawyer) wrote:</p>
<blockquote>
<p>You mean "cherrypicking like Facets" right? ;)</p>
</blockquote>
<p>Sorry, I'm a noob, not knowing whom to credit :]</p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=350402012-12-24T08:47:50Ztrans (Thomas Sawyer)
<ul></ul><p>I just release a gem called backload that basically handles this. But in working through the problem set, it's become clear that there are some features of a good load callback that just can't be done in pure Ruby. I've already mentioned the #relative_require issue. Another issue, is that it would be nice to get the full path of the loaded file, e.g. as an additional option called :fullpath. There's no way to do that in pure Ruby b/c there is no way to lookup a load path (see issue <a class="issue tracker-2 status-2 priority-4 priority-default" title="Feature: Feature lookup and checking if feature is loaded (Assigned)" href="https://redmine.ruby-lang.org/issues/6376">#6376</a>). Even if there were, it would be redundant b/c Ruby is just going to look it up again in the C code.</p>
<p>So putting it all together, it seems this really needs to be implemented in the C if it is to be done right. I do not know if that would mean it cannot be an optional standard library, or not.</p>
<p>I almost did not bother to release backload (and I still have half a mind to yank it) b/c it can't be as complete and solid an implementation as it really ought, but I suppose for some uses it would suffice.</p>
<p><a href="http://rubyworks.github.com/backload" class="external">http://rubyworks.github.com/backload</a></p> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=367512013-02-22T09:27:06Zko1 (Koichi Sasada)
<ul><li><strong>Category</strong> set to <i>core</i></li><li><strong>Assignee</strong> set to <i>matz (Yukihiro Matsumoto)</i></li></ul><p>I'm sorry I don't catch up this discussion.<br>
I assigned this ticket to matz, but I'm not sure matz is good person to handle it.<br>
Please correct me.</p>
<a name="Basically-I-agree-with-this-proposal"></a>
<h1 >Basically, I agree with this proposal.<a href="#Basically-I-agree-with-this-proposal" class="wiki-anchor">¶</a></h1> Ruby master - Feature #7548: Load and Require Callbackshttps://redmine.ruby-lang.org/issues/7548?journal_id=688582017-12-25T18:15:09Znaruse (Yui NARUSE)naruse@airemix.jp
<ul><li><strong>Target version</strong> deleted (<del><i>2.6</i></del>)</li></ul>