13

メインアプリのアプリケーションコントローラーにbefore_filterフックがあり、次のような動作をします:(フラッシュにリンクを配置するだけでなく、メッセージが表示されますが、質問には関係ありません。ルートにアクセスするだけです。方法)

class ApplicationController < ActionController::Base
  before_filter :set_link

  def set_link
    flash[:notice] = items_path
  end
end

これはアプリでは正常に機能しますが、作成したエンジンのコントローラーに入ると、例外が発生します

No route matches {:controller=>"items", :action=>"index"}

エンジン内では、プレフィックスが付いていない限り、ルートヘルパーはエンジン用であることを理解していますmain_app

したがって、アプリケーションコントローラのメソッドを次のように変更します。

  def set_link
    flash[:notice] = main_app.items_path
  end

例外を取り除きますが、私は本当にそれをする必要はありません。エンジンにmain_appルートを認識させるための別の解決策はありますか?

編集:

これは、アプリケーションレイアウトがパスヘルパーを呼び出す場合にも発生します。したがって、エンジンがmain_appのレイアウトに統合されるように設計されている場合、この問題はそこでも発生します。

4

5 に答える 5

19

マウント可能なエンジンは、このように機能するように設計されています。つまり、メインのアプリルートとエンジンルートを分離します。

2セットのルートをマージする場合は、非分離エンジンを使用できます。最初のステップはisolated_namespace、エンジン定義のメソッド呼び出しを削除することです。

module MyEngine
  class Engine < Rails::Engine
    isolate_namespace MyEngine # remove this line
  end
end

2番目のステップは、でルートを変換するmy_engine/config/routes.rbことです。これから実行する必要があります。

MyEngine::Engine.routes.draw do
  # stuff that routes things
end

これに:

Rails.application.routes.draw do
  # stuff that routes things
end

アプリケーションのルートでメソッド呼び出しを削除mountします。

App::Application.routes.draw do
  mount MyEngine::Engine => "/engine" # remove this line
end

この方法で行う主な利点は次のとおりです。

  1. Railsにモンキーパッチを適用する必要はありません。deviseがこれを行うことは知っていますが、これはエンジンがレールに存在しなかった時代の残り物である可能性があります。

  2. アプリケーションルートにエンジンを取り付ける必要はありません。一方、挿入ポイントをより正確に制御したい場合は、メインルートの後に(または前に、この質問に対する答えがありません)すべてのエンジンルートが呼び出されるため、これは逆効果になる可能性があります。

エンジンに関するドキュメントを探している場合は、Engineクラスのrailsドキュメントがかなり良い出発点です。このテーマに興味がある場合は、(まだ読んでいない場合は)それらを読むことを強くお勧めします。

于 2011-10-01T20:25:24.703 に答える
4

私はこれを行う方法を考え出しました。問題は、分離された名前空間内にあります。エンジンをアプリと統合し、同じレイアウト(メインアプリからのパスヘルパーがある場合があります)を共有するために、私はこれを行いました:

config/routes.rbまずエンジンから外しました

次に、エンジンクラスからisolate_namespaceを削除しました

module MyEngine
   class Engine < Rails::Engine
-    isolate_namespace MyEngine
   end
 end
end

エンジンにロードされたファイルを追加しました:

module ActionDispatch::Routing
  class Mapper
    def mount_my_engine_at(mount_location)
      scope mount_location do
        #Declare all your routes here
      end
    end
  end
end

最後に、メインアプリではconfig/routes.rb、エンジンを「マウント」する代わりに、メソッドを呼び出すことができます

mount_my_engine_at "mount_location"

これは基本的に、エンジンをメインアプリから分離するのではなく、メインアプリの一部として「マウント」します。これは、Deviseが行う方法にも似ています。

于 2011-09-30T17:16:00.007 に答える
2

あなたはisolate_namespaceを保持することができます。エンジンroutes.rbで

MyEngine::Engine.routes.draw do
  ...
  root to: "something#index"
end

Rails.application.routes.draw do
  get "something", to: "my_engine/something#index"
end

そして、メインアプリのroutes.rbで

Rails.application.routes.draw do

  mount MyEngine::Engine => "/anything_you_want"

  root to: "main#index"
end

このようにして、公開するルート(および公開しないルート)を選択できます。

于 2013-04-21T02:51:06.497 に答える
1

Railsエンジンガイドで強く推奨されているように、isolate_namespaceを保持し、これを行うことができます。

# inside your main_app's config/routes.rb
Rails.application.routes.draw do
  root to: 'home#index'

  mount MyEngine::Engine, at: "/" 
end
# inside your engine's controller
module MyEngine
  class SomeController << ::ApplicationController
    # include main_app's route helpers
    helper Rails.application.routes.url_helpers

  end
end

また、gem内で、すべてのURLヘルパーの前に正しいルーティングプロキシメソッド(my_engine.pages_pathなど)が付いていることを確認してください。

main_appのレイアウトとエンジンのコントローラーは、これらのURLヘルパーをメインアプリに正しくルーティングしてリンクします。メインアプリのどこかに「main_app」プレフィックスを追加する必要はありません。唯一の欠点は、エンジンのルートをmain_appのルートパスにマウントしていることです。これは、同じ名前のルートと衝突する可能性があります。non-isolate_namespaceを実行する場合、これはとにかく予想されます。

于 2019-12-03T21:33:58.890 に答える
0

最も簡単な方法は、メインアプリとエンジンの両方でルートを描画して、両方にアクセスできるようにすることです。

[MyEngine::Engine, App::Application].each do |app|
  app.routes.draw do
    # Declare all your routes here
  end
end
于 2012-07-25T16:53:35.443 に答える