2

私はいくつかの異なるプロジェクトで使用するエンジン(私/私が働いている会社によって開発された)を持っています。Rails 3.1 w / Assetsパイプラインで動作するように変換したところ、すべてが動作しているようです...ほとんどの場合。

私の問題は、UsersControllerアプリ固有のスパイスを少し使っての機能を拡張する必要があることですが、それを行うための最良の方法がわかりません。エンジンはアクションを定義しませんUsers#showが、このアプリはそれを必要とするので、ルートファイルに追加しました:

JobEngine::Application.routes.draw do
  root :to => 'home#index'

  resource :users, :only => [:show]
  resources :jobs, :only => [:show]
end

次に、私のアプリケーションで、UsersControllerを作成しました。

class UsersController < MyEngine::UsersController
  def show
  end
end

次に、ビューを作成しusers/show.html.hamlました。問題のある行の1つだけを表示するために、ビューを削除しました。

= link_to "Somewhere", job_path(3)

これにより、次のようなエラーが発生しますundefined method 'job_path' for #<#<Class:0x00000102d69900>:0x00000102d4ed30>

これは奇妙なことです。なぜなら、アプリの継承を作成する前は、問題なく機能していたからです。UsersControllerMyEngine::UsersController

私がrake routesコンソールで行うとき、これらの行があります:

users GET   /users(.:format)    {:action=>"show", :controller=>"users"}
job GET     /jobs/:id(.:format) {:action=>"show", :controller=>"jobs"}

クラス定義を次のように変更できます。

class UsersController < ApplicationController

その後、リンクは正常に機能します。ただし、エンジンのコントローラーはMyEngine::UsersControllerすでにから継承していApplicationControllerます。アプリにコードを入れることができApplicationController(のようにbefore_filter)、期待どおりに実行されるので、クラス定義が最終的にアプリにヒットすることがわかっていますApplicationControllerが、job_pathヘルパーが機能しないのはなぜですか?

表示アクションを次のように変更すると、次のようになります。

def show
  job_path(3)
end

エラーが発生します:

ActionController::RoutingError (No route matches {:action=>"show", :controller=>"jobs", :id=>3}):
app/controllers/users_controller.rb:9:in `show'

これは、実際にはjob_pathをメソッドとして認識しているため、さらに混乱しますが、どういうわけか、ルーターはすべての正しいパラメーターを使用してどこに行くかを選択していません。

私は何が間違っているのですか?エンジンコントローラーの機能を拡張する正しい方法は何ですか?ここでエンジン機能の拡張に関する質問を見ました。

そして、そのコード例に従って、クラス定義を変更して代わりに再度開くようにしましMyEngine::UsersControllerたが、それでもまったく同じ結果が得られます。job_path(NUMBER)

アップデート:

さて、私は何が起こっているのか理解しました。エンジンにjob_pathルートがあり、アプリケーションにjob_pathルートがあるとします。エンジンのコントローラーを介してアクセスされたページを表示している場合は、を使用してエンジンのヘルパーを呼び出すことができjob_pathますが、を使用してメインアプリケーションのヘルパーを呼び出すこともできますmain_app.job_path

同様に、アプリケーションのコントローラーの1つを介してアクセスするページを表示している場合は、でエンジンのヘルパーにアクセスし、でmy_engine.job_path独自のアプリケーションのヘルパーにアクセスしますjob_path。これは、のようなものがあることを前提としていますmount MyEngine::Engine => "/my_engine", :as => 'my_engine'

アプリケーションからエンジンコントローラーを継承すると、ルートヘルパーが完全に変更され、コントローラー/ビューのライフサイクルを通じてエンジンのコンテキストにいると見なされます。ですから、私の問題を解決するために私が本当にしなければならないのは、それを変更することだけでmain_app.job_path(3)、それは機能します。

この解決策は少し...奇妙に感じるので、私は完全には満足していません。たぶん、私はこのページに、別の非継承ページで使用される部分を持っています。これで、リンクヘルパーは2つのページのいずれかでのみ機能しますが、両方では機能しません= \ここで何かが不足しています...?

4

2 に答える 2

1

メインアプリのルートのマウントパスを以下で変更してみてください。

mount MyEngine::Engine => "/"

これはあなたの問題を解決するでしょう。

于 2011-12-27T07:46:04.410 に答える
0

このアプローチを機能させることはできますが、セマンティクスはクリーンなアーキテクチャを作成しません。Usersこれは、コントローラーの重複から推測できます。これは、一部のUser機能がAppEngineで処理され、一部が親アプリ自体で処理されることを意味します。

代わりに、アプリ内に一意に存在する機能と、AppEnginegemにパッケージ化されている機能について考えてください。おそらくJobEngineでは、あなたがそれを呼んでいるように、あなたのUsersコントローラーは実際にあり、アプリには、 CRUD、プロファイル、メッセージキューなどを処理UsersStatisticsControllerする「真のジェネリック」があります。UsersController

それらを(明確な命名法を与えるのではなく)単一のコントローラーに統合する必要があると思われる場合は、さまざまな機能を結合できる 名前空間コントローラーを作成するのが最善です。

これにより複雑さが増しますが、これが最も適切なソリューションであると一般的に議論の余地があります。 これについてのSOに関する別の投稿があります

于 2011-12-27T18:20:58.613 に答える