2012-01-06 61 views
9

給定了一個gem,它定義了與我寫的一些代碼衝突的頂級類,是否有可能要求gem的所有類都被分組到一個模塊中我可以定義?例如,如果一個unsafe_gem定義一個類:將Ruby gem加載到用戶定義的名稱空間中

class Word 
    # ... some code 
end 

,我需要這樣的:

class Word 
    # My word class. 
end 

module SafeContainer 
    # This obviously doesn't work 
    # (i.e. the gem still defines ::Word). 
    require 'unsafe_gem' 
end 

所以,我可以區分以下:

Word.new # => The class I defined. 
SafeContainer::Word.new # => The class defined by the gem. 

一些進一步的細節:我的代碼(例如'Word'類)已經包裝在它自己的名稱空間中。不過,我希望能夠向用戶提供啓用「語法糖」形式的選項,這使得可以在頂級命名空間下直接訪問某些類。然而,這會與我使用的其中一個寶石產生名稱衝突,該寶石定義了頂級類。目前提出的解決方案都沒有效果,因爲創業板實際上依賴於其全球定義的類在那裏;所以沒有定義班級打破了寶石。當然,這個gem有多個文件,並且單獨將它的文件放入一個模塊似乎是一個非常脆弱的解決方案。目前,我已經找到了唯一的解決方法是這樣的:

begin 
    # Require the faulty gem. 
    require 'rbtagger' 
rescue 
    # If syntactic sugar is enabled... 
    if NAT.edulcorated? 
    # Temporarily remove the sugar for the clashing class. 
    Object.const_unset(:Word); retry 
    else; raise; end 
ensure 
    # Restore syntactic sugar for the clashing class. 
    if NAT.edulcorated? 
    Object.const_set(:Word, NAT::Entities::Word) 
    end 
end 

我不知道爲什麼,但是這使得我的腳趾甲捲曲。任何人都有更好的解決方案?

回答

4

另一個可能更好的答案來自this問題。的事實

利用的類和模塊都只是對象,像這樣:

require 'unsafe_gem' 
namespaced_word = Word 
Word = nil 


# now we can use namespaced_word to refer to the Word class from 'unsafe_gem' 

#now your own code 
class Word 
    #awesome code 
end 

你必須確保unsafe_gem只定義一個類,那你require它,你定義自己的班前和模塊,所以你不會意外地把自己的東西設置爲nil

1

我認爲你最好的選擇是將自己的代碼包裝在一個模塊中。根據你寫的代碼數量,這可能會或可能不會是一個巨大的痛苦。但是,確保你的代碼不會與其他人發生衝突是最好的方式。

所以你Word類成爲

module LoismsProject 
    class Word 
    #some awesome code 
    end 
end 

這樣,你可以放心地require 'unsafe_gem'

0

簡單的答案是「否」

如果我們有一個文件'word.rb';

class Word 
    def say 
    puts "I'm a word" 
    end 
end 

我們嘗試和require它,它會一直加載在全局範圍內。

如果您知道創業板只是一個文件,您可以做到以下幾點。

module SafeContainer 
    module_eval(File.read("word.rb")) 
end 

但這不太可能在你的情況下工作。