问题
I mounted in my app the RailsAdmin engine ( according to the instructions from the wiki ) using
mount RailsAdmin::Engine => '/backend', :as => 'rails_admin'
I had to extend one controller from the engine to add a before_filter. When running my app in development, my extension and the other engine features are working perfectly.
However I have an issue in writing functional tests using Test::Unit for my before_filter. The filter kicks in at the right moment and works as expected, but once the action "tweaked" by the before filter redirects to index ( which is an expected result ), I get the following routing error:
ActionController::RoutingError: No route matches {:controller=>"rails_admin/main"}
The code leading to the exception lies in the engine's method to redirect to index or to the previous page ( kind of referer ); here is the code for the method
def back_or_index
if params[:return_to].presence
params[:return_to]
else
index_path
end
I discovered that when running the app in development, the url_for call triggered by index_path is supplied with the proper path_segments ( i.e.: :model_name => 'user' ) so that the route below is matched
index GET|POST /:model_name(.:format) rails_admin/main#index
On the other hand, when running the tests, the path_segments are not supplied, thus the :model_name constraint is not satisfied when looking for a matching route.
Since I'm new to engines, can someone tell me what I'm missing?
To me it looks as if the engine should take into consideration the fact that is mounted generating the index_path, but as I said I'm not an expert in this....
回答1:
use_route was not enough: the call to index_path was failing anyway.
After lots of debugging, I am not yet completely sure about the root cause of why the same code was not working both in test and development.
What I observed is that index_path in development is able to infer the model_name from the url of the request, while in test is is not.
Although ugly, my solution was to override the method as follows in app/controllers/rails_admin/main_controller.rb
module RailsAdmin
class MainController
# Override to fix a routing error when running tests
def back_or_index
if params[:return_to].presence && params[:return_to].include?(request.host) && (params[:return_to] != request.fullpath)
params[:return_to]
else
# forward :model_name as default_url_options is not aware of it in tests
index_path( :model_name => params[:model_name] )
end
end
end
end
In my controller specs for MainController I do the following
put :edit, { :model_name => 'user', :id => root.id, :user => { :role => :root }, :use_route => :rails_admin }
And this is what I have in my routes
devise_for :users
mount RailsAdmin::Engine => '/backend', :as => 'rails_admin'
mount Rich::Engine => '/rich', :as => 'rich'
If anyone has a better solution, sharing would be really appreciated!
来源:https://stackoverflow.com/questions/14281505/rails-3-2-engines-routes-not-working-in-test-cases