2012-02-18 2 views
1

私は、ユーザーが特定のディレクトリのクラスを自動要求、インスタンス化、および登録できるようにするGemを開発しています。私はこれを達成する方法がわかりません。これはこれまで私が思い付いたことです...Ruby:ディレクトリ内のすべてのファイルを要求してインスタンス化する方法は?

どのように呼び出されているのかわからずにクラスをインスタンス化できますか?

+0

最も簡単な解決策は、クラスの後にファイルの名前を付けることです。次に、ファイル名を使用できます。 – Linuxios

答えて

5

拡張機能をソフトウェアに書き込むためのシステムを作っているようですが、これは基本的な実装で、最初の構造を借りています。拡張クラスはいくつかの一般的なメソッドを共有するなどいくつかの点でおそらくすべて似ているので、すべての拡張クラスが継承する基本クラスExtensionを持つことが理にかなっています。

実際には、ユーザーがクラスを継承したときにそれを検出してサブクラスをリストに追加することができるため、これは非常に有効です。ここではコンセプトコードのいくつかの証拠である:

class Extension 
    class << self 
    attr_reader :list 
    end 
    @list = [] 

    def self.inherited(klass) 
    @list << klass.new 
    end 
end 

# The MyExt class would be in another file, loaded by require. 
class MyExt < Extension 
end 

p Extension.list # => [#<MyExt:0xb777d884>] 

あなたには、いくつかの理由でサブクラス化を使用しない場合、Extensionはモジュールで、代わりにinheritedincludedフックを使用するためにも同様に簡単です。

個人的には、すぐにクラスをインスタンス化する理由が表示されないため、私は.newへの呼び出しを削除しますが、それはあなた次第です。私はクラスのリストを保存するだけです。

1

これは私の頭をしばらく傷つけてしまった興味深い考えです。私はグーグルで即座に解決策を見つけることができませんでした。は

  • クラスにファイル名を関連付けるために命名規則を使用し

    • は、すべてのロードされたクラスを追跡し、彼らは
    • に来るように新しいものをつかむ上のイントロスペクタのいくつかの並べ替えを使用します。私は、三つの基本的なアイデアを思い付きました必要なクラスが将来の包含のために自分自身を登録できるようにする

    私は最初のオプションが最も好きだと決めました。特定の方法でファイルを構造化する必要はありません。また、クラスを拡張して、このように必要となることを知ることもできます。

    classes = ObjectSpace.each_object(Class).to_a 
    Dir[Dir.pwd + '/extensions/*.rb'].each do |file| 
        require file 
        changed_classes = ObjectSpace.each_object(Class).to_a 
        (changed_classes - classes).each do |extension_class| 
        MyApp.extensions << extension_class 
        end 
        classes = changed_classes 
    end 
    
  • +1

    これは、ファイルに定義されているすべての新しいクラスが「拡張機能」として登録され、ヘルパークラスを持つことが不可能になるため、悪いことです。 –

    +0

    かなり優雅な精神!私は 'classes'と' changed_classes'の違いが気に入っています。 +1。 – Linuxios

    +0

    @DavidGrayson - 私は同意します。問題を回避するための何らかの種類のコンベンションを考え出すことができますが、それはアプリケーションに固有のものになります。私はよりクリーンな、第4の方法を考えたいと思います。 – checkorbored

    関連する問題