Skip to content

No route matches Anonymous controller problem #636

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
g3d opened this issue Nov 13, 2012 · 10 comments
Closed

No route matches Anonymous controller problem #636

g3d opened this issue Nov 13, 2012 · 10 comments
Labels

Comments

@g3d
Copy link

g3d commented Nov 13, 2012

As i see, anonymous controller doesn`t work. I expect test custom 404 error handling, but have only errors:

rspec spec/controllers/errors_controller_spec.rb

No DRb server is running. Running in local process instead ...
WARNING: Nokogiri was built against LibXML version 2.7.8, but has dynamically loaded 2.8.0
.FFFF

Failures:

  1) ApplicationController error raising should handle ActionController::RoutingError correctly
     Failure/Error: get :routing_error
     ActionController::RoutingError:
       No route matches {:controller=>"anonymous", :action=>"routing_error"}
     # ./spec/controllers/errors_controller_spec.rb:42:in `block (3 levels) in <top (required)>'

  2) ApplicationController error raising should handle ActionController::UnknownController correctly
     Failure/Error: get :my_membership
     ActionController::RoutingError:
       No route matches {:controller=>"anonymous", :action=>"my_membership"}
     # ./spec/controllers/errors_controller_spec.rb:46:in `block (3 levels) in <top (required)>'

  3) ApplicationController error raising should handle ActionController::RoutingError correctly
     Failure/Error: get :action_not_found
     ActionController::RoutingError:
       No route matches {:controller=>"anonymous", :action=>"action_not_found"}
     # ./spec/controllers/errors_controller_spec.rb:50:in `block (3 levels) in <top (required)>'

  4) ApplicationController error raising should handle ActionController::RoutingError correctly
     Failure/Error: get :record_not_found
     ActionController::RoutingError:
       No route matches {:controller=>"anonymous", :action=>"record_not_found"}
     # ./spec/controllers/errors_controller_spec.rb:54:in `block (3 levels) in <top (required)>'

Finished in 2.21 seconds
5 examples, 4 failures

Failed examples:

rspec ./spec/controllers/errors_controller_spec.rb:41 # ApplicationController error raising should handle ActionController::RoutingError correctly
rspec ./spec/controllers/errors_controller_spec.rb:45 # ApplicationController error raising should handle ActionController::UnknownController correctly
rspec ./spec/controllers/errors_controller_spec.rb:49 # ApplicationController error raising should handle ActionController::RoutingError correctly
rspec ./spec/controllers/errors_controller_spec.rb:53 # ApplicationController error raising should handle ActionController::RoutingError correctly

cat spec/controllers/errors_controller_spec.rb

require 'spec_helper'
describe ErrorsController do
  describe "GET 'error_404'" do
    it "returns http success" do
      get 'error_404'
      response.status.should be(404)
    end
  end
end

describe ApplicationController, type: :controller do
  controller do
    def routing_error
      raise ActionController::RoutingError.new("not_found")
    end

    def unknown_controller
      raise ActionController::UnknownController.new("not_found")
    end

    def method
      raise AbstractController::ActionNotFound.new("not_found")
    end

    def record_not_found
      raise ActiveRecord::RecordNotFound.new("not_found")
    end
  end

  describe "error raising" do
    it "should handle ActionController::RoutingError correctly" do
      get :routing_error
      response.status.should be(404)
    end
    it "should handle ActionController::UnknownController correctly" do
      get :my_membership
      response.status.should be(404)
    end
    it "should handle ActionController::RoutingError correctly" do
      get :action_not_found
      response.status.should be(404)
    end
    it "should handle ActionController::RoutingError correctly" do
      get :record_not_found
      response.status.should be(404)
    end
  end
end

cat app/controllers/application_controller.rb

class ApplicationController < ActionController::Base

  layout 'public'

  protect_from_forgery
  before_filter :check_auto_login
  around_filter :rescue_access_denied

  def check_auto_login
    mid = params.delete(:mid)
    expires_in = params.delete(:expires_in)
    checksum = params.delete(:checksum)
    if mid.present? || expires_in.present? || checksum.present?
      begin
        if not_expired?(expires_in) && checksum_matches?(checksum, request.env['QUERY_STRING'])
          member = Member.find_by_id(mid)
          sign_in :member, member
        end
      rescue Exception => e
        Rails.logger.warn("Auto login failed #{e.message}, #{e.backtrace[0..5].join("\n")}")
      end
      redirect_to url_for(params)
    end
  end

  def rescue_access_denied
    begin
      yield
    rescue CanCan::AccessDenied
      redirect_to unauthorized_path and return
    end
  end

  def get_chrome_frame
    render layout: false
  end

  def unauthorized
    render text: "unauthorized", status: 401
  end

  unless Rails.application.config.consider_all_requests_local
    exceptions_404 = [
      ActionController::RoutingError,
      ActionController::UnknownController,
      AbstractController::ActionNotFound,
      ActiveRecord::RecordNotFound ]
    rescue_from *exceptions_404, with: lambda { |exception| render_error 404, exception }
  end

  protected

  def render_error(status, exception)
    respond_to do |format|
      format.html { render template: "errors/error_#{status}", layout: 'public', status: status }
      format.all { render nothing: true, status: status }
    end
  end

  def get_referring_member
    Member.find_by_guid(cookies[:referred_by])
  end

  def get_referring_member_name
    if (referring_member = get_referring_member)
      referring_member.name
    else
      ""
    end

  end

  private

  def not_expired?(expires_in)
    Time.current.to_i < Integer(expires_in) if expires_in.present?
  end


  def after_sign_in_path_for(resource)
    case resource
    when Member
      if params[:member] && params[:member][:redirect].present?
        params[:member][:redirect]
      elsif current_member.engaged_member?
        member_dashboard_path
      else
        prospect_dashboard_path
      end
    when User
      if can? :access, :admin
        params[:user].try(:[], :redirect) || admin_dashboard_path
      else
        root_path
      end
    else
      super
    end
  end
end

I already looked to similar cases (like #573 or http://stackoverflow.com/questions/7027518/no-route-matches-rspecs-anonymous-controller) but it doesn`t helped me, so i writed this issue.

rails (3.2.1)
rspec (2.11.0, 2.10.0)
rspec-core (2.11.1, 2.10.1)
rspec-expectations (2.11.3, 2.10.0)
rspec-mocks (2.11.3, 2.10.1)
rspec-rails (2.11.4, 2.10.1)

@andrewhavens
Copy link

I am running into a similar issue. Not sure how to test this type of scenario.

@alindeman
Copy link
Contributor

Thanks for the detailed report. I'll see if I can figure out what's going on here soon; in the mean time, you might be able to test the coverage you want by testing this at a higher level using request specs.

@pcasaretto
Copy link
Contributor

I think this is expected, see this:
c8523df
However, I believe this assumption is very limiting.
Maybe we can force the routing somehow?

@ku1ik
Copy link
Contributor

ku1ik commented Dec 1, 2012

I have similar issue and wondering what's the best way to handle this.

@vanstee
Copy link
Contributor

vanstee commented Dec 6, 2012

Anonymus controllers only create resource routes. So routes like routing_error wont exist but stuff like index or show should work. Here's the spec that defines this functionality:

https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs/anonymous-controller#anonymous-controllers-only-create-resource-routes

Does this resolve the issue you were seeing?

@alindeman
Copy link
Contributor

It is possible to do something like this:

require "spec_helper"

describe ApplicationController do
  controller do
    def custom
      render :text => "custom!"
    end
  end

  describe "#custom" do
    before do
      routes.draw { get "custom" => "anonymous#custom" }
    end

    it "responds to GET" do
      get :custom
      expect(response.body).to eq "custom!"
    end
  end
end

YMMV as to whether it's a good idea for your app :) And @vanstee is correct in that we only draw the default resources routes for you.

@pcasaretto
Copy link
Contributor

Very nice! Thanks @alindeman . That should be on the docs.
Quick question, will the drawn routes get rolled back, or do we have to do it on our own?

@alindeman
Copy link
Contributor

The routes are rolled back automatically. If you'd like to submit a documentation update, I'd likely pull it in :)

@ngoral
Copy link

ngoral commented Apr 20, 2018

I got a problem with this too: usage of routes.draw in before block (not in it) causes all following tests to fail with No route matches ....
Am I missing something?

@henrik
Copy link
Contributor

henrik commented Nov 15, 2018

Another data point, without having delved deep into the issue:

If I add an index action (do def index; render text: "hi"; end) and then do get :index, everything works fine. If I try something else like get :show or get :foobar (having added a corresponding action), I get the route error.

index is also the only action I see in the doc examples (https://relishapp.com/rspec/rspec-rails/docs/controller-specs/anonymous-controller), so maybe it has some special magic.

EDIT: Ah, the docs go into this: https://relishapp.com/rspec/rspec-rails/docs/controller-specs/anonymous-controller#anonymous-controllers-only-create-resource-routes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants