Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Named routes in mounted rails engine

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

like image 229
Markus Avatar asked Nov 06 '11 18:11

Markus


People also ask

How many types of routes are there in Rails?

Rails RESTful Design which creates seven routes all mapping to the user controller. Rails also allows you to define multiple resources in one line.

What is Mount in Rails routes?

Mount within the Rails routes does the equivalent of a Unix mount . It actually tells the app that another application (usually a Rack application) exists on that location. It is used mostly for Rails Engines.

What are Rails engines?

Well, simply put a Rails engine is the miniature edition of a Rails application. It comes with an app folder, including controllers, models, views, routes, migrations... The difference though is, that an engine won't work on its own.


2 Answers

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) 
like image 50
James A. Rosen Avatar answered Sep 23 '22 06:09

James A. Rosen


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 
like image 37
Epigene Avatar answered Sep 23 '22 06:09

Epigene