Issue #4969 has been updated by Thomas Sawyer.


Okay, I finally got around to digging into this a bit more. The issue can be seen from this simple example. 

Given a local directory containing:

  fixture/
    abbrev.rb

Then:

  $ irb
  >> $LOAD_PATH.unshift('./fixture')
  => ["./fixture", "/usr/local/lib/ruby/gems/1.9.1/gems/wirble-0.1.3/lib", "/usr/local/lib/ruby/site_ruby/1.9.1", "/usr/local/lib/ruby/site_ruby/1.9.1/x86_64-linux", "/usr/local/lib/ruby/site_ruby", "/usr/local/lib/ruby/vendor_ruby/1.9.1", "/usr/local/lib/ruby/vendor_ruby/1.9.1/x86_64-linux", "/usr/local/lib/ruby/vendor_ruby", "/usr/local/lib/ruby/1.9.1", "/usr/local/lib/ruby/1.9.1/x86_64-linux"]
  >> require '/usr/local/lib/ruby/1.9.1/abbrev.rb'
  => true
  >> Abbrev 
  => Abbrev
  >> require 'abbrev'
  => false

Even though we loaded the standard abbrev.rb file using an absolute path, Ruby thinks that the subsequent require is for the same file. But it is not b/c the files in the 'fixture' directory should be taking precedence over the other location since it is earlier in the $LOAD_PATH.


----------------------------------------
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