2

だから私は 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") を使用してコントローラーに手動で含めるかどうか疑問に思っています。それによってロード順序が変更される場合があります。

4

3 に答える 3

1

Module#class_evalを使用してオーバーライドできます。

メインアプリでは、

MountedEngineHelper.class_eval do
  def advanced_helper
    ...
  end
end

このようにして、エンジン ヘルパーで定義された他のメソッドを引き続き使用できます。

于 2013-01-02T10:57:19.493 に答える
0

お手数をおかけしますが、よろしくお願いいたします。これは本当に問題だと思います。そして、それはRails 3.2.3にまだ存在しているので、私は問題を提出しました。

私が思いついた最も臭いのない回避策は、「ハーフエイリアスメソッドチェーン」を実行することです。

module MountedEngineHelper
  def advanced_helper
    ...
  end
end

module MyHelper
  def advanced_helper_with_extra_behavior
    advanced_helper
    extra_behavior
  end
end

明らかな欠点は、ヘルパーが呼び出されるようにテンプレートを変更する必要があることです。少なくとも、そこでは余分な動作の存在を明示的にします。

于 2012-05-26T14:33:40.587 に答える
0

Rails4 からのこれらのリリース ノートは、この問題に魅力的に関連しているようで、修正されている可能性があります。

http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#helpers-loading-order

于 2013-06-20T13:29:59.063 に答える