2011-07-22 81 views
0

我试图在我的一个新项目中使用Module#autoload为我的类设置自动加载。这几乎是行得通的 - 问题是首先使用一个常量来自动加载,它带有“未初始化的常量”的错误,但在第二次使用时常量按预期工作。Ruby 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 

应用/models/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> 

我怎样才能得到我想要的行为(不初始误差)?

+0

不它工作,如果你'自动加载:雪碧,“精灵”'明确? “自动加载?(:Sprite)”在调用Autoload模块之后会得到什么? – Andy

+0

显式地执行它没有什么区别,''autoload?(:Sprite)'在'init.rb'中的所有点都返回nil,这很好奇,因为它最终会加载它。 –

回答

2

问题是您在模块Autoload的范围内致电autoload。在这种情况下,ruby期待或创建的是符号Autoload::Sprite的自动加载,当你想要的只是Sprite

幸运的修复很简单:

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

或者你也可以显式调用Object自动加载的,因为这就是你的“目标范围”的自动加载类最有可能的是:

Object.autoload ... 
+0

我不相信它创建了一个'Autoload :: Sprite'的符号,因为它不起作用(并且它不会向我解释它为什么会出错,然后工作)。定义自动加载包括正常工作,谢谢! –

相关问题