Effects of require

I’ve been using python a lot lately, so I’ll start with how that
works. In python, when you’re dynamically loading code, you do
something like

module = import(mod_name_as_string, …)

and then you have a module object that you can call methods on, etc.
In ruby, if I understand correctly, you can do

require some_string

and it parses that file and puts stuff into the global namespace. Is
there a sane way to determine exactly what was changed by that
require? Suppose I have a directory layout like this:

root//plugin/<plugin_names>/plugin.rb

and I want to load all the plugin.rb files, I can use
Dir[“root/*/plugin/#{name}/plugin.rb”] and then use require_relative
on the resulting list of strings, but how do I know what modules are
being defined in those plugin.rb files?

tsuraan wrote:

In ruby, if I understand correctly, you can do
require some_string
and it parses that file and puts stuff into the global namespace. Is
there a sane way to determine exactly what was changed by that
require?

No, there’s not. Requiring a file executes that file, which often
has the side-effect of defining some constants. If you only care
about top-level constants, or know the namespace of the constants
you care about, you can save the list before require, and subtract
that from the list after require.

root//plugin/<plugin_names>/plugin.rb
and I want to load all the plugin.rb files, I can use
Dir[“root/*/plugin/#{name}/plugin.rb”] and then use require_relative
on the resulting list of strings, but how do I know what modules are
being defined in those plugin.rb files?

You don’t, unless you can guarantee to always use a specific mapping
between directory structures and namespaces - none is enforced (nor
could be enforced) in Ruby, as it is in, say, Java class file loading.

The code being run on require could change anything, through monkey
patching, ObjectSpace, etc, even changing running object instances.

Clifford H…

You don’t, unless you can guarantee to always use a specific mapping
between directory structures and namespaces - none is enforced (nor
could be enforced) in Ruby, as it is in, say, Java class file loading.

Ok, but there is a way to accomplish what I needed, anyhow. I
switched to putting my functions into classes that inherit from a
common base. When the plugin files are loaded, ruby calls the
.inherited method on my base class, which tells me that new plugins
have been registered. At least there’s a way to track some activity,
if not all activity.

The code being run on require could change anything, through monkey
patching, ObjectSpace, etc, even changing running object instances.

Yeah, I expect that to be the case; I just wish ruby had sane
namespacing of the introduction of constants. I guess it wouldn’t
matter, since things like monkey-patching are so popular in ruby, so
the effects of a single file would rarely be contained in its
namespace anyhow, but I’ve always been irritated by the fact that
loading a file doesn’t give any hint as to what new modules/classes
have been introduced to the global namespace. Am I alone in this
view?

Even when a library does use modules, it doesn’t generally give clean
namespacing. For example, the ‘drb’ library wraps all its code in the
DRb module, but then lifts some of its classes into the global
namespace:

Module.constants.sort.grep /drb/i
=> []

require ‘drb’
=> true

Module.constants.sort.grep /drb/i
=> [:DRb, :DRbIdConv, :DRbObject, :DRbUndumped]

Shouldn’t the DRbIdConv, DRbObject, and DRbUndumped just stay under
the DRb module? They’re promoted to the global namespace at the
bottom of drb/drb.rb, but why is this considered a good idea? Are
hygenic namespaces considered ugly in ruby?

On Dec 17, 2010, at 10:57 AM, tsuraan wrote:

Shouldn’t the DRbIdConv, DRbObject, and DRbUndumped just stay under
the DRb module? They’re promoted to the global namespace at the
bottom of drb/drb.rb, but why is this considered a good idea? Are
hygenic namespaces considered ugly in ruby?

I don’t have any definitive answers to your questions, just a few
observations:

Yes it is considered bad form for a library to pollute the global
namespace.

But it isn’t clear that the same rules should apply to Ruby core classes
or the standard library.

And don’t forget that the existing standard library has evolved over
almost 10 years, what seems obvious now might have been considered
needless concern then.

Gary W.