During the migration of a huge application from rails2 to rails3 I encountered a seriously baflling error. In almost every controller spec, i got the the following error: [ruby] Caught ActionController::RoutingError: No route matches {:controller=>"home"} [/ruby] This got me puzzling. If i ran a single controller-spec it worked, running the whole bunch failed (using rake spec
or rspec spec/controllers/**/*_spec.rb
). So I posted a question on stackoverflow and on the rspec-mailing-list. When googling, all related issues seemed to be caused by actual errors in config/routes.rb
, but my application was working, it was generating all links correctly. It only failed when testing, and only when running the full suite. What i did to solve this, was actually compare the log-files of a single group of working controllers with the total set of controllers. And there it was: the routing table was erased by the first spec i ran. We have a base controller class where the shared behaviour for our API-controllers is placed. To test this controller we create, inside our spec, a new controller-class that derives from that baseclass and add a new route. In rails2 and rspec1 this spec looked as follows (simplified): [ruby] require 'spec_helper' class WsTestController < Ws::BaseController def index end end ActionController::Routing::Routes.draw do |map| map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end describe WsTestController do context "without authentication" do it("asks for Basic authentication") { get :index response.status.should contain("401") } end context "with authentication" do # .. snipped the rest .. end end [/ruby] Now apparently what happens now, in rails3, is that instead of adding routes, the entire routing table is replaced by these routes. Whoops. So in effect, this was almost the only controller-spec that actually worked. When i disabled this spec, or more specifically the part where the routes are manhandled, all my controller and view specs worked again. So how do you fix this? How can you dynamically add routes in rails3 at runtime? Luckily google found the solution here. So my working spec for rails3/rspec2 looks as follows (and that doesn't interfere with my other specs) : [ruby] require 'spec_helper' class WsTestController < Ws::BaseController def index render :text => 'this worked' end end describe WsTestController do before(:each) do begin _routes = Dpplus::Application.routes _routes.disable_clear_and_finalize = true _routes.clear! Dpplus::Application.routes_reloader.paths.each{ |path| load(path) } _routes.draw do # here you can add any route you want get "ws_test/index" end ActiveSupport.on_load(:action_controller) { _routes.finalize! } ensure _routes.disable_clear_and_finalize = false end end context "without authentication" do it("asks for Basic authentication") { get :index response.status.should contain("401") response.header["WWW-Authenticate"].should contain('Basic') } end context "with authentication" do # ..snipped ... end end [/ruby] Hope this helps :)
Comments
Add comment