私は、ユーザーが特定のディレクトリのクラスを自動要求、インスタンス化、および登録できるようにするGemを開発しています。私はこれを達成する方法がわかりません。これはこれまで私が思い付いたことです...Ruby:ディレクトリ内のすべてのファイルを要求してインスタンス化する方法は?
どのように呼び出されているのかわからずにクラスをインスタンス化できますか?
私は、ユーザーが特定のディレクトリのクラスを自動要求、インスタンス化、および登録できるようにするGemを開発しています。私はこれを達成する方法がわかりません。これはこれまで私が思い付いたことです...Ruby:ディレクトリ内のすべてのファイルを要求してインスタンス化する方法は?
どのように呼び出されているのかわからずにクラスをインスタンス化できますか?
拡張機能をソフトウェアに書き込むためのシステムを作っているようですが、これは基本的な実装で、最初の構造を借りています。拡張クラスはいくつかの一般的なメソッドを共有するなどいくつかの点でおそらくすべて似ているので、すべての拡張クラスが継承する基本クラス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
はモジュールで、代わりにinherited
のincluded
フックを使用するためにも同様に簡単です。
個人的には、すぐにクラスをインスタンス化する理由が表示されないため、私は.new
への呼び出しを削除しますが、それはあなた次第です。私はクラスのリストを保存するだけです。
これは私の頭をしばらく傷つけてしまった興味深い考えです。私はグーグルで即座に解決策を見つけることができませんでした。は
私は最初のオプションが最も好きだと決めました。特定の方法でファイルを構造化する必要はありません。また、クラスを拡張して、このように必要となることを知ることもできます。
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
これは、ファイルに定義されているすべての新しいクラスが「拡張機能」として登録され、ヘルパークラスを持つことが不可能になるため、悪いことです。 –
かなり優雅な精神!私は 'classes'と' changed_classes'の違いが気に入っています。 +1。 – Linuxios
@DavidGrayson - 私は同意します。問題を回避するための何らかの種類のコンベンションを考え出すことができますが、それはアプリケーションに固有のものになります。私はよりクリーンな、第4の方法を考えたいと思います。 – checkorbored
最も簡単な解決策は、クラスの後にファイルの名前を付けることです。次に、ファイル名を使用できます。 – Linuxios