Named routes in mounted rails engine

2019-02-01 10:54发布

问题:

I'm making a small rails engine which I mount like this:

mount BasicApp::Engine => "/app"

Using this answer I have verified that all the routes in the engine are as the should be:

However - when I (inside the engine) link to a named route (defined inside the engine) I get this error

undefined local variable or method `new_post_path' for #<#<Class:0x000000065e0c08>:0x000000065d71d0>

Running "rake route" clearly verifies that "new_post" should be a named path, so I have no idea why Rails (3.1.0) can't figure it out. Any help is welcome

my config/route.rb (for the engine) look like this

BasicApp::Engine.routes.draw do
  resources :posts, :path => '' do
                resources :post_comments
                resources :post_images
        end
end

I should add that it is and isolated engine. However paths like main_app.root_path works fine - while root_path does not

回答1:

The right way

I believe the best solution is to call new_post_path on the Engine's routes proxy, which is available as a helper method. In your case, the helper method will default to basic_app_engine, so you can call basic_app_engine.new_post_path in your views or helpers.

If you want, you can set the name in one of two ways.

# in engine/lib/basic_app/engine.rb:
module BasicApp
  class Engine < ::Rails::Engine
    engine_name 'basic'
  end
end

or

# in app/config/routes.rb:
mount BasicApp::Engine => '/app', :as => 'basic'

In either case, you could then call basic.new_posts_path in your views or helpers.

Another way

Another option is to not use a mounted engine and instead have the engine add the routes directly to the app. Thoughtbot's HighVoltage does this. I don't love this solution because it is likely to cause namespace conflicts when you add many engines, but it does work.

# in engine/config/routes.rb
Rails.application.routes.draw do
  resources :posts, :path => '' do
                resources :post_comments
                resources :post_images
  end
end

# in app/config/routes.rb:
# (no mention of the engine)


回答2:

On Rails 4 the engine_name directive did not work for me.
To access a named route defined in engine's routes from engine's own view or controller, I ended up using the verbose

BasicApp::Engine.routes.url_helpers.new_post_path

I recommend defining a simple helper method to make this more usable

# in /helpers/basic_app/application_helper.rb

module BasicApp::ApplicationHelper
  def basic_app_engine
    @@basic_app_engine_url_helpers ||= BasicApp::Engine.routes.url_helpers
  end
end

With this in place you can now use

basic_app_engine.new_post_path

In case you need to access your main application helper from the engine you can just use main_app:

main_app.root_path


回答3:

use the below in you app to access the engine routes

MyApp::Engine.routes.url_helpers.new_post_path