On Wed, 13 Oct 2004 16:11:32 +0900
In article <1097651490.544184.31335.nullmailer / x31.priv.netlab.jp>
[[ruby-list:40086] Re: require 中に例外が発生したときの対処について]
Yukihiro Matsumoto <matz / ruby-lang.org> wrote:

> |・考えてみた解決案3
> |
> | そんなケースはレアなので、あきらめる。
> 
> 当面はそれでもよいような気がします。「ほしいなあ」と繰り返し
> 叫べば親切な人がeval.cをハックして上記の機能を実現してくれる
> かもしれません。

mod_ruby附属の auto-reload を改良した奴を使っています。ファイル
を変更すると依存しているもの全部読み直してくれるので便利。
# 注: 再入(スレッド)考慮してません。
#     クラス編成が変わったときのような場合はプロセス再起動しましょう

----
require 'rbconfig'

module AutoReload
  LIBRARY_MTIMES = {}
  LIBRARY_DEPS = {}
  PROCESSING_FILE = []
  
  LIBRARY_PATH_CACHE = {}
  SYSLIB = /^(#{Regexp.quote(Config::CONFIG['rubylibdir'])}|#{Regexp.quote(Config::CONFIG['sitelibdir'])})/o
  
  def AutoReload.find_library(lib)
    cache = LIBRARY_PATH_CACHE
    unless (cvalue = cache[lib]).nil?
      return cvalue
    end
    case File.extname(lib)
    when ".so"
      return cache[lib] = false
    when ".rb"
      libname = lib.sub(/\.rb$/, '')
    else
      libname = lib
      solib = true
    end
    if libname[0] == ?/
      file = File.expand_path(libname).untaint
      if File.file?(rbname = file + ".rb")
        if SYSLIB =~ file
          cache[lib] = false
        else
          cache[lib] = rbname
        end
      elsif solib && File.file?(file + ".so")
        cache[lib] = false
      end
    else
      for dir in $:
        file = File.expand_path(libname, dir).untaint
        if File.file?(rbname = file + ".rb")
          if SYSLIB =~ file
            return cache[lib] = false
          else
            return cache[lib] = rbname
          end
        elsif solib && File.file?(file + ".so")
          return cache[lib] = false
        end
      end
    end
    nil
  end
  
  def require(lib)
    unless file = AutoReload.find_library(lib)
      return super
    end
    
    library_deps = LIBRARY_DEPS
    library_mtimes = LIBRARY_MTIMES
    processing_file = PROCESSING_FILE
    
    deps = library_deps[file] ||= {}
    for f in processing_file
      return false if f == file
      fdeps = library_deps[f]
      fdeps[file] = 1
      fdeps.update(deps)
    end
    
    processing_file.push file
    begin
      do_load = false
      for f, in deps
        if File.mtime(f) != library_mtimes[f]
          do_load = true
          break
        end
      end
      mtime = File.mtime(file)
      if do_load || mtime != library_mtimes[file]
        load(file)
        library_mtimes[file] = mtime
        true
      else
        false
      end
    ensure
      processing_file.pop
    end
  end
end

include AutoReload              # override Kernel#require



―[ Tietew ]――――――――――――――――――――――――――
 メ : tietew / tietew.net / tietew / raug.net / tietew / masuclub.net
ホペ: http://www.tietew.net/     Tietew Windows Lab.
      http://www.masuclub.net/   鱒倶楽部
指紋: 26CB 71BB B595 09C4 0153  81C4 773C 963A D51B 8CAA