別ファイルに定義されたクラスを動的に読み直したいのだけど、どうやっていいやら。単に eval
とかやると同じクラス名はもう使ってるぜ?
って警告されるわけだし、Class::new do ... end
は違うくさいし、remove_const
はメソッド内から呼べないself.remove_const
がないよって怒られるわけだから、他に方法があるのかもしれない? 定義したクラス名.class_eval("remove_const(:CONST)")
ってやればいいらしい([ruby-list:38594] Re: cgi.rbのremove_const)。これで上手くいくかどうか実装してみよう。し。
プラグインみたいな。ずっと動きっぱなしのプログラムで、ある一部分だけソースからもう一度読み直してやりたい。
# ML の過去ログで面白いのハケン [ruby-list:27327] Haiku. こういうの好き
class PluginManager def initialize @plugins = {} end def class_name(filename) File::basename(filename, ".rb").capitalize end def load(filename) class_name = class_name(filename) eval(open(filename) {|f| f.read }, binding) # インスタンス作成して @plugin に突っ込む。 eval("@plugins[class_name] = #{class_name}::new") end def unload(filename) class_name = class_name(filename) PluginManager.class_eval("remove_const(:#{class_name})") @plugins.delete(class_name) end def each @plugins.each do |k,v| yield k, v end end end pm = PluginManager::new pm.load("foo.rb") f = PluginManager::Foo::new pm.unload("foo.rb") f = PluginManager::Foo::new # => uninitialized constant PluginManager::Foo (NameError) =begin # foo.rb class Foo end =end
みたいな感じかなぁ……もっとスマートにできるような気がする。しかもコレだと PluginManager の外からロードしたクラスにアクセスできる(丁度上の f のように )んだよね。もう一個 Plugin クラスとか作ってその中にロードしたクラスのインスタンス突っ込んでやろうか。