2011-07-22 5 views
0

Module#autoloadを使用して私の新しいプロジェクトで私のクラスのオートローディングを設定しようとしています。ほとんど問題なく動作しています。最初に定数をオートロードする場合は、「初期化されていない定数」でエラーが発生しますが、2番目の使用法では定数が期待どおりに機能します。Rubyのオートロードは、定数の最初の言及でエラーをスローする

問題を示すコード:

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

んあなたが '自動読み込み:スプライト、スプライト"を明示的に使用していれば動作しますか? 'オートロード?(:スプライト)'は、オートロードモジュールの呼び出しの後にあなたを得ますか? – 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'のためのシンボルを作成しています。代わりに、それが動作しません。なぜ、エラーが発生してから動作するのかがわかりません。 includeにautoloadを定義すると正しく動作しますが、ありがとう! –

関連する問題