Ruby autoload在第一次提到常量时抛出错误

时间:2011-07-22 09:07:39

标签: ruby autoload

我正在尝试使用Module#autoload在我的新项目中为我的课程设置自动加载功能。它几乎正常工作 - 问题在于,首先使用常量进行自动加载,它会出现“未初始化常量”错误,但在第二次使用时,常量会按预期工作。

说明问题的代码:

init.rb:

# Load lib, other directories will be autoloaded
APPLICATION_ROOT=File.expand_path(File.dirname(__FILE__))
$:.unshift(APPLICATION_ROOT)
Dir.glob("#{APPLICATION_ROOT}/patches/*").each {|p| require p}
Dir.glob("#{APPLICATION_ROOT}/lib/*").each {|p| require p}

# Test autoloading
include Autoload
begin
  puts Sprite.new.inspect
rescue
  puts "Caught an error"
end
puts Sprite.new.inspect # will not error

贴剂/ string.rb:

class String
  def camelize
    self.split("_").map{|word| word.capitalize}.join
  end
end

LIB / autoload.rb:

module Autoload
  Dir.glob("#{APPLICATION_ROOT}/app/*/*").each do |path|
    classname = File.basename(path).gsub(/.rb$/,'').camelize
    autoload classname.to_sym, path
  end
end

应用程序/模型/ sprite.rb:

puts "Sprite Required!"
class Sprite
  puts "Sprite Defining!"
  def initialize
    puts "Sprite Initialized!"
  end
end
puts "Sprite Defined!"

输出:

Sprite Required!
Sprite Defining!
Sprite Defined!
Caught an error
Sprite Initialized!
#<Sprite:0x000000024ee920>

如何获得我想要的行为(没有初始错误)?

1 个答案:

答案 0 :(得分:2)

问题是您在模块autoload的范围内调用Autoload。在类似情况下,红宝石期待或创建的是符号Autoload::Sprite的自动加载,当您想要的只是Sprite时。

幸运的是,修复很简单:

module Autoload
  def self.included(mod)
    # ...
    # Call autoload on the scope of the includer
    mod.autoload ...
  end
end

或者您也可以在Object上明确调用自动加载,因为这是自动加载类的“目标范围”最有可能的地方:

Object.autoload ...