2011-12-09 16 views
1

我試圖爲一個包創建「autorequire」,即如果Ruby遇到一個未知的常量,它會嘗試要求它,如果需求成功,則繼續它停止的地方。現在,我有這樣的事情:需要一個未知的常量,並繼續

def autoload(&block) 
    yield 
rescue NameError => e 
    if e.message[/constant/] 
    require e.name.to_s.downcase rescue LoadError raise 
    retry 
    end 
    raise 
end 

所以,如果我用這個像

autoload { 
    print "Hello, " 
    x = ArrayFields.new 
    x << "World!" 
    puts x[0] 
} 

正如預期的那樣,將打印Hello, Hello, World!。所以它處理常量的需求,但從頭開始執行整個給定的塊。那麼,我該如何跳到失敗發生的地方呢?這主要是爲了學術興趣,所以我也對這種嘗試中的任何危險感興趣。

回答

3

無法從救援條款跳回到異常之前的位置。做一個你想做的更可行的方法是重寫const_missing

+0

我修改了該文檔中給出的示例以保留原始錯誤(未初始化的常量)。但爲什麼這不作爲一個班輪運行:'需要文件救援LoadError super.const_missing(name)'。它只會作爲'開始要求文件救援LoadError super.const_missing(名稱)結束',並且它必須在開始結束後包含換行符等。 –

+0

@Tatu:內聯救援的語法是'exp1 rescue exp2'。使用內聯救援不能指定例外類型。 – sepp2k

+0

這是一個錯字(儘管語法是允許的),但那和你的提醒讓我弄清楚爲什麼它不起作用。 LoadError不是StandardError,因此它不受無類型救援的影響。在後面的例子中,也要記住這一點,如果救援不在自己的生產線上,無論您如何將其寫入一行,它總是內聯救援。 –

0

Ruby自動加載,至少在Ruby 2.0中會存在。

+0

請注意,儘管ruby的自動加載功能與OP代碼的功能不同(即您必須使用ruby的自動加載「預先註冊」文件)。 – sepp2k