Issue #4969 has been updated by Thomas Sawyer.


hi, abbrev.rb is not part of wedge. I just used 'abbrev.rb' as an easy to understand example of the potential problem. Wedge (which has been renamed to 'Loadable' in the latest release), has a "load wedge" that makes it possible to circumvents any possible name clashes. Now it would be nice if everyone followed proper practice and thus avoided all possible clashes, but that is often not the case, like it or not. This can be easily seen from this very partial list, https://github.com/rubyworks/loadable/blob/master/INFRACTIONS.md.

Even so, the issue I've run into isn't this per se.* I wrote Loadable to deal with it. The problem is that I can't make Loadable work as it should b/c of the way in which Ruby is handling feature caching. See point #7 of this discussion for what I mean. Thanks.

*Though IMO it would be a good idea for Ruby to deal with this.

----------------------------------------
Bug #4969: Subtle issue with require
http://redmine.ruby-lang.org/issues/4969

Author: Thomas Sawyer
Status: Feedback
Priority: Normal
Assignee: 
Category: 
Target version: 
ruby -v: -


If I have a library with same name as Ruby standard library in load path (as an example):

  lib/abbrev.rb

There is conflict with loading. Ok, I work around:

  require 'rbconfig'

  # Notice that rubylibdir takes precendence.
  LOCATIONS = ::RbConfig::CONFIG.values_at(
    'rubylibdir', 'archdir', 'sitelibdir', 'sitearchdir'
  )

  #
  def require_ruby(file)
    LOCATIONS.each do |loadpath|
      if path = lib_find(loadpath, file)
        return path
      end
    end

    raise LoadError, "no such file to load -- #{fname}"
  end

  private

    SUFFIXES = ['.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']

    # Given a +loadpath+, a file's relative path, +relname+, and 
    # options hash, determine a matching file exists. Unless +:load+
    # option is +true+, this will check for each viable Ruby suffix.
    # If a match is found the full path to the file is returned,
    # otherwise +nil+.
    def lib_find(loadpath, relname)
      if SUFFIXES.include?(File.extname(relname))
        abspath = File.join(loadpath, relname)
        File.exist?(abspath) ? abspath : nil
      else
        SUFFIXES.each do |ext|
          abspath = File.join(loadpath, relname + ext)
          return abspath if File.exist?(abspath)
        end
      end
      nil
    end

Now I can do:

  require 'abbrev'
  require_ruby 'abbrev'

And it works fine. But, if I do:

  require_ruby 'abbrev'
  require 'abbrev'

The second is not loaded because somehow it seems to confuse it for the first in $LOADED_FEATURES.

I realize this is a very subtle issue and not likely to effect most people, but it presents a big problem for some of my work (e.g. wedge gem)

How is Ruby confusing the two? Can it be fixed? Or is there at least a work around?



-- 
http://redmine.ruby-lang.org