だから私は Rails 3.0 Engine (gem) を持っています。
app/controllers/advanced_controller.rb でコントローラーを提供し、app/helpers/advanced_helper.rb で対応するヘルパーを提供します。(もちろん、いくつかのビュー)。
これまでのところ、コントローラー/ヘルパー/ビューは、gem を使用してアプリケーションで自動的に利用できるようになりました。
しかし、ローカル アプリケーションがエンジン内の AdvancedHelper からヘルパー メソッドを選択的に上書きできるようにしたい (理想的には「super」を呼び出せるようにしたい)。それは、完全に合理的な (そして私は一般的だと思う) 設計を許可したいのはかなり合理的なことでしょうか?
問題は、それを機能させる方法が見つからないようです。アプリケーションが独自の app/helpers/advanced_helper.rb (AdvancedHelper) を定義している場合、エンジンからのものはまったく読み込まれません。そのため、(super を呼び出さずに) そこにあるすべてのヘルパー メソッドを置き換えたい場合に機能します。 、ただし、オーバーライドしたいだけの場合はそうではありません。
そういうのは実際には意味があるので、別の名前を選びます。私のローカルのものを ./app/helpers/local_advanced_helper.rb (LocalAdvancedHelper) と呼びましょう。このヘルパーは読み込まれます。元のエンジンの AdvancedHelper にないメソッドをそこに配置すると、ビューで使用できます。
しかし、エンジンの AdvancedHelper と同じ名前のメソッドをそこに配置すると、ローカルのメソッドは決して呼び出されません。AdvancedHelper (エンジンから) が LocalAdvancedHelper (アプリから) よりもコール チェーンの前にあるようです。確かに、デバッガーをオンにして helpers.ancestors を見ると、まさにそれが起こっていることであり、先祖チェーンで必要な逆の順序になっています。したがって、AdvancedHelper (エンジンから) は理論的には「super」を呼び出して (アプリから) LocalAdvancedHelper を呼び出すことができますが、もちろんそれを行う意味はあまりありません。
でもやりたいことが… できない。
アプリがエンジンからのヘルパー メソッドを選択的にオーバーライドできるこのデザインを提供する方法はありますか?
なぜそれがこのように機能しているのか、誰にも説明がありますか? Rails の実際のソース コードを調べてみましたが、すぐにわからなくなってしまいました。この部分のコードは、非常に抽象的で、いくつかの場所に分かれています。
これはかなり難解な質問です。私は悲観的ですが、誰もが何らかのアイデアを持っていると思います。驚かせてください!
== 更新
さて、Rails コードのどの部分がどこで呼び出されているかを理解するために、各ヘルパーに「def self.included ; debugger ; end」を配置し、デバッガーで例外を発生させてスタック トレースを表示します。
Rails のコードはあちこち飛び回っていて、かなり混乱しています。
しかし、「標準」名のヘルパー (WidgetController の WidgetHelper など) は、特定のコントローラーの「マスター」ビュー ヘルパー モジュールに含めるために、他のヘルパーとは異なる Rails コードによって呼び出されることは明らかです。ヘルパーに別の名前を付けてから、("helper OtherNamedAdvancedHelper") を使用してコントローラーに手動で含めるかどうか疑問に思っています。それによってロード順序が変更される場合があります。