Hatena::ブログ(Diary)

某社文系エンジニアの日記

2010-10-16

Rials3 でEnginesを使ったプラグインのクラスを再オープンする

18:03 |

http://d.hatena.ne.jp/hkweb/20101010/1286727068

このエントリで書いた通り、rails3ではEnginesを使ったプラグインを簡単に作成できる。ただ、Enginesプラグインを作るにあたって色々と困ったことが起きたのでちょっと書いておく。

まず前提として、自分がつくろうと思ったのはASP的なプラグインで、ASPを提供する顧客によっては若干の仕様変更が必要な場合があるので、顧客ごとにプロジェクトを作成する。複数のプロジェクトを運用することになるが、共通化出来るコア部分をプラグイン化してメインアプリから読み込み、顧客毎の固有の需要に応えるために場合によってはプラグインで定義されたクラスをそれぞれのプロジェクトのメイン側でオープンクラスして、機能を拡張するようなイメージ。

以下、気づいた点&困ったこと点リスト

プラグイン側とメイン側で同名のクラスを定義していた場合は、メイン側のクラスが優先される(再オープンできない)


controllerで試した結果、上記の通りだった。その他Modelとかではまだ試してない。

単純に同名のクラスを定義していると、メインの方が優先され、プラグインの方は無視される模様(多分) おそらくloadpath($:)上の仕様。

なので、通常の状態だとプラグイン側で定義されたクラスをメイン側で再オープンできない。同名クラスを再オープンしたい場合はメイン側クラスのファイルを以下のように書くと、なんとか再オープンできた。

app/controllers/samples_controller.rb

require 'plugins/enginetest/app/controllers/samples_controller'
class SamplesController
  def index
    #iroiro
  end 
end

requireでプラグインのsamples_controllerを読み込んで、

その下ですぐに再オープンする感じ。

プラグイン側で定義されたクラスをメイン側で再オープンしているとき、再オープンしている側のクラスを編集してブラウザをリロードしても変更点が反映されない。


上記の通りの問題が発生した。おそらくプラグインのクラスがサーバ起動時にキャッシュされてリロード毎に読み込み直されない仕様になっているためだと思って色々調べたとところ、以下のような記事を見つけた。

http://stackoverflow.com/questions/1633852/rails-auto-reloading-plug-in-development-mode

http://nhw.pl/wp/2009/01/07/reloading-your-plugin-in-development-mode

rails3では

ActiveSupport::Dependencies.load_once_paths

はなくなったようで、

ActiveSupport::Dependencies.autoload_once_paths

があったので、

pluginのinit.rbで

ActiveSupport::Dependencies.autoload_once_paths.delete(reloadable_path) if "development" == RAILS_ENV

のようにやってみたが、結果は変わらずだった。

autoload_once_paths

の他に

autoload_paths

もあったので、そちらでも試してみたが、変わらず。

最終的には以下の方法で、なんとかアクセス毎にプラグインクラスをリロードできるようになった。

app/controllers/application_controllers.rb

...
before_filter :force_reload
def force_plugin_reload  
    ActiveSupport::Dependencies.load_file "#{Rails.root}/app/controllers/samples_controller.rb" if "development" == RAILS_ENV
end
...


そろそろちゃんとRailsソースコードを直接読んだりしていこうと思う。

トラックバック - http://d.hatena.ne.jp/hkweb/20101016/1287219834