How can I make routes from a Rails 3 engine available to the host application?
Solution 1
Change config.routes
in your engine to:
Rails.application.routes.draw do # NOT MyEngineName::Engine.routes.draw
resources :classrooms
end
The way you have it, the routes are only available in the MyEngineName::Engine
namespace and not in the rest of the host rails application.
There used to be a blog post with more info, but unfortunately it is no longer available:
Solution 2
I had the same problem, and found this in the documentation:
Since you can now mount an engine inside application’s routes, you do not have direct access to Engine‘s url_helpers inside Application. When you mount an engine in an application’s routes, a special helper is created to allow you to do that. Consider such a scenario:
# config/routes.rb
MyApplication::Application.routes.draw do
mount MyEngine::Engine => "/my_engine", :as => "my_engine"
get "/foo" => "foo#index"
end
Now, you can use the my_engine helper inside your application:
class FooController < ApplicationController
def index
my_engine.root_url #=> /my_engine/
end
end
Solution 3
For me also help to add
require 'engine' if defined?(Rails)
to my main gem file (lib/.rb).
Good example - https://github.com/mankind/Rails-3-engine-example/blob/master/lib/dummy.rb
Related videos on Youtube
PerfectlyNormal
Updated on September 20, 2020Comments
-
PerfectlyNormal over 3 years
I have a Rails 3 application with several engines containing additional functionality. Each engine is a separate service that customers can purchase access to.
I am, however, having a problem with routes from the engines that aren't readily available to the controllers and views.
controller:
class ClassroomsController < ApplicationController .. respond_to :html def index respond_with(@classrooms = @company.classrooms.all) end def new respond_with(@classroom = @company.classrooms.build) end .. end
app/views/classrooms/new.html.haml
:= form_for @classroom do |f| .. f.submit
config/routes.rb
in engine:MyEngineName::Engine.routes.draw do resources :classrooms end
config/routes.rb
in app:Seabed::Application.routes.draw do mount MyEngineName::Engine => '/engine' ... end
lib/my_engine_name.rb
in engine:module MyEngineName class Engine < ::Rails::Engine end end
attempting to go to
/classrooms/new
results inNoMethodError in Classrooms#new Showing app/views/classrooms/_form.html.haml where line #1 raised: undefined method `hash_for_classrooms_path' for #<Module:0x00000104cff0f8>
and attempting to call
classrooms_path
from any other view results in the same error. I can, however, callMyEngineName::Engine.routes.url_helpers.classrooms_path
and get it working. I'm thinking I might have defined the routes wrong, but can't find another way that works.Tried running the app with both Passenger (standalone and Apache module) and WEBrick (rails server). Using latest Rails from Git (
7c920631ec3b314cfaa3a60d265de40cba3e8135
). -
PerfectlyNormal over 13 yearsDoing that, removing the mount-call in my app-routes, and scoping in engine-routes (
scope '/engine' do
) and everything works. Thanks a lot :) -
bowsersenior over 13 yearsCool, thanks for the info on the other steps needed to get the Engine routes working.
-
Xavier Shay about 12 yearsFor Rails 3.1 and later, remove the
map
parameter to the block (just remove the entire|map|
part). -
Jwan622 almost 8 yearsWhat if I have a catch-all route at the bottom of my main app? How do I ensure these engine's routes are not just appended to the bottom of the host app's routes?
-
bowsersenior almost 8 years@Jwan622 Not sure about that. There may be some useful info in this answer: stackoverflow.com/a/7040520/457819
-
Jwan622 over 7 yearsfor code inside the Engine, do you need to prepend routes to its own controllers with the engine's name as well? Or can you just use
classrooms_path
from inside the Engine? -
Alexander Kuznetsov over 7 yearsJwan622, for the own routes you can use helpers without any prefixes.
-
0xtobit over 6 yearsUnfortunately, the blog post link seems to be dead.
-
bowsersenior over 6 yearsThanks for letting me know. Couldn't find a new URL for the blog post. Let me know if you find one. Added a note to the answer to indicate the link was down.