2012-01-06 5 views
9

私が書いたコードと衝突するトップレベルのクラスを定義するgemがあれば、すべてのクラスがモジュール内でグループ化されるようにgemを要求することは可能でしょうか?私は定義することができますか?Ruby gemをユーザー定義のネームスペースにロードする

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

いくつかの詳細:を私は区別できるように

class Word 
    # My word class. 
end 

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

:たとえば、unsafe_gemがクラスを定義する場合:

class Word 
    # ... some code 
end 

私のようなものが必要になります私のコード(例えば、 'Word'クラス)は既に独自の名前空間にラップされています。しかし、私は、トップレベルの名前空間の下で直接アクセスできるいくつかのクラスを作成する、 "構文的な砂糖"のフォームを有効にするオプションをユーザに提供できるようにしたい。しかしこれは、私が使用しているトップクラスのクラスを定義する宝石と名前の衝突を作り出します。現在提案されているソリューションのどれも、宝石がそこに存在する世界的に定義されたクラスに実際に頼っているため動作しません。クラスの定義を解除すると宝石が壊れます。もちろん、この宝石には複数のファイルがあり、モジュールにファイルを個別に要求することは非常に脆弱な解決策です。現在、私が発見した唯一の回避策はこれです:

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

もう1つ、おそらく良い答えはthisです。

クラスとモジュールがちょうどそうのように、オブジェクトであるという事実を利用してください:あなたはあなた自身のクラスを定義する前にunsafe_gemのみ1つのクラスが定義されていることを確認して、あなたrequireそのことをする必要が

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 

あなたが誤って独自のものを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 

しかし、これはあなたのケースではうまくいかないでしょう。

関連する問題