Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Failing functional test of a named route

#3263

Given the following named route:

map.accept_invitation '/accept_invitation/:id', :controller => "invitations", :action => "accept", :method => "get"

and the following controller:

class InvitationsController < ApplicationController
  def accept
  end
end

This test will fail:

class InvitationsControllerTest < ActionController::TestCase
  test "the post accept invitation should be successful" do
    get :accept, :id => "1"
    assert_response :success
  end
end

...with the following error:

ActionController::RoutingError: No route matches
{:controller=>"invitations", :action=>"accept", :id=>"1"}

while the app does not complain upon receiving the request:

http://localhost:3000/accept_invitation/3

I have posted a dummy app to reproduce the problem at

git://github.com/giuseb/spec_named_route.git

--Giuseppe

Reported by Giuseppe Bertini · September 26th, 2009 @ 05:41 PM

State: invalid
Milestone: none
Assigned to: nobody
Importance: none

Activity

  1. sr.iniv.t
    sr.iniv.t

    Giuseppe, can you please specify the rails version you're on?

    Seems to work for me on 2.3.3:

    ts > rails -v
    Rails 2.3.3
    
    ts > cat config/routes.rb 
    ActionController::Routing::Routes.draw do |map|
      map.accept_invitation '/accept_invitation/:id', :controller => "invitations", :action => "accept", :method => "get"
      map.connect ':controller/:action/:id'
    end
    
    ts > cat app/controllers/invitations_controller.rb 
    class InvitationsController < ApplicationController
      def accept; end
    end
    
    ts > cat test/functional/invitations_controller_test.rb 
    require 'test_helper'
    
    class InvitationsControllerTest < ActionController::TestCase
      test "the post accept invitation should be successful" do
        get :accept, :id => "1"
        assert_response :success
      end
    end
    
    ts > ruby -Itest test/functional/invitations_controller_test.rb 
    Loaded suite test/functional/invitations_controller_test
    Started
    .
    Finished in 0.082477 seconds.
    
    1 tests, 1 assertions, 0 failures, 0 errors
    

    September 26th, 2009 @ 07:57 PM

  2. Giuseppe Bertini
    Giuseppe Bertini

    Hi, I am on rails 2.3.4.

    I believe that the reason your test passes is that, after the named route in question, you have the catch-all route (:controller/:action/:id). What happens if you remove the latter?

    Cheers,
    Giuseppe

    September 26th, 2009 @ 10:24 PM

  3. CancelProfileIsBroken
    CancelProfileIsBroken
    • Tag changed from functional, routing, test to bugmash, functional, routing, test

    September 27th, 2009 @ 11:30 AM

  4. John Trupiano
    John Trupiano

    verified, when removing the default routes this error does indeed occur.

    It's noteworthy that removing :method => 'get' from the route eliminates the problem.

    September 27th, 2009 @ 04:13 PM

  5. Elad Meidar
    Elad Meidar

    +1 verified.

    it might have something to do with the use of accept as a method name? maybe get :accept is confusing for some reason...

    September 27th, 2009 @ 08:10 PM

  6. Elad Meidar
    Elad Meidar

    No it's not.... i tried a different action name and it still failed... possibly this has something to do with the catch-all route that may be required.

    September 27th, 2009 @ 08:19 PM

  7. Gaius Centus Novus
    Gaius Centus Novus

    Does the view app/views/invitations/accept.html.erb exist? Your empty definition of accept implicitly renders this view (or the more general app/views/inivitations/accept.erb). If that doesn't exist, you'll get a 404.

    September 27th, 2009 @ 10:41 PM

  8. Gaius Centus Novus
    Gaius Centus Novus

    Also, you don't mean :method => :get, you mean :conditions => { :method => :get }.

    September 27th, 2009 @ 10:42 PM

  9. Matías Flores
    Matías Flores

    I verified the behavior you described on 2-3-stable, but I'm not sure this is a bug.
    I agree with Gaius, correct syntax is :conditions => {:method => :get}, not just :method => 'get'

    September 28th, 2009 @ 05:13 AM

  10. Giuseppe Bertini
    Giuseppe Bertini

    Suppose you have the following two named routes (along with controller actions and .erb templates):

    ActionController::Routing::Routes.draw do |map|
      map.accept_invitation '/accept_invitation/:id', :controller => "invitations", :action => "accept", :conditions => {:method => "get"}
      map.view_invitation '/view_invitation/:id',   :controller => "invitations", :action => "view",   :method => "get"
    end
    

    and the following two test:

    test "the get accept invitation should be successful" do
      get :accept, :id => "1"
      assert_response :success
    end
    test "the get view invitation should be successful" do
      get :view, :id => "1"
      assert_response :success
    end
    

    The first passes, while the second returns an error, seemingly supporting Gaius and Matías.
    However, if you stick the following 2 URLs in your browser:

    http://localhost:3000/accept_invitation/1
    http://localhost:3000/view_invitation/1

    ...then the FORMER request fails, while the latter succeeds.

    September 28th, 2009 @ 06:28 AM

  11. Giuseppe Bertini
    Giuseppe Bertini

    Which leads to the following proposal.

    • The testing framework simply enforces the proper :conditions => {:method => :get} syntax, so there's no problem there.
    • It's really the routing that behaves funny.

    Reasonable?

    September 28th, 2009 @ 08:24 AM

  12. Pablo Calderon
    Pablo Calderon

    I have run into the same problem with restful routes. Something as simple as the following will fail in testing.

    routes.rb
    map.resources :products
    
    products_controller_test.rb
    test "should get index" do
      get :index
      assert_response :success
    end
    
    Whatever format the testing framework requires you would think that the generated routes will be correct. This must be a bug, surely resource routes are meant to be testable in functional tests.
    

    October 27th, 2009 @ 06:21 PM

  13. Prem Sichanugrist (sikachu)
    Prem Sichanugrist (sikachu)
    • State changed from new to invalid
    1. If you put :method => "get" in your route, and not :conditions => {:method => :get}, you just made typos there
    • You should specify :method as symbol
    • If you don't put it in :conditions, path will be recognized as :requirement => {:method => "get}. So no way the test will pass.

    However, somehow the :method will be included in the params[] when you request via browser. So in the post number 12 you will be able to visit view_invitation_path.

    I don't think this is really a problem. You just need to use :conditions => {:method => :get}, and your problem will go away

    January 25th, 2010 @ 01:51 PM