Error: Redirecting in a way that never completes

I am trying to use the session hash to restrict access to a portion of a web site. I have 2 controllers. The first is 'main' for general access and the second is 'protected' for restricted access. I have appended my 'protected' controller to the end of this message. The operation is real simple. There are only 2 users. If the user is logged in as 'user', he's supposed to get re-directed to the roster page. If the user is logged in as 'admin', he's supposed to get re- directed to the admin page. Otherwise, the user is re-directed to the login action which is under the main controller.

The problem that I'm having is that when the user is properly logged in as either 'user' or 'admin', instead of being re-directed to the appropriate page I get an error message from FireFox saying, "Firefox has detected that the server is redirecting the request for this address in a way that will never complete." The URL bar of the browser shows that the browser is trying to display the proper page. If I try the same thing with IE, the redirected page just never gets displayed. The Firefox error message goes on to explain that the problem can sometimes be caused by disabling or refusing to accept cookies. That's not the case here.

I really haven't got a clue as to why this re-direction doesn't work. Does anyone know what the problem is; and, more importantly, how to fix it?

Thanks for any input.

      ... doug

------------- Protected Controller ---------------- class ProtectedController < ApplicationController

  before_filter :accessControl

  def roster   end

  def logout   end

  def accessControl     case session[:rank]       when "admin"         redirect_to :controller=>'protected',:action=>'admin'       when "user"         redirect_to :controller=>'protected',:action=>'roster'       else         redirect_to :controller=>'main',:action=>'login'     end     return false   end end

The problem is that redirect_to does not return so your method is always returning false even though it is setting the redirect header. Try this instead:

  def accessControl     case session[:rank]       when "admin"         redirect_to :controller=>'protected',:action=>'admin' && return       when "user"         redirect_to :controller=>'protected',:action=>'roster' && return       else         redirect_to :controller=>'main',:action=>'login' && return     end     return false   end

doug wrote:

actually, since it seems you are checking the return value, you should do:

    def accessControl
case session[:rank]
when "admin"
redirect_to :controller=>'protected',:action=>'admin' && return true
when "user"
redirect_to :controller=>'protected',:action=>'roster' && return true else
redirect_to :controller=>'main',:action=>'login' && return true
end
return false
end

William Pratt wrote:

I just noticed that you are using this method as a before filter. This really makes sense now as returning false would stop the chain, but since the redirect header is set, the browser would get redirected, then the before filter would get hit again, stop the chain, but redirect, and on and on and on.

One other thing, you should make the accessControl method protected so that it can’t be called directly because posting to it and setting rank manually would bypass access control, so this should be the final method:

`

Thanks for the input, Bill. What you say makes perfect sense and it would seem that your solution would just work out of the box. However, what actually happens is that I get a syntax error:

/var/www/rails/app/controllers/protected_controller.rb:15: syntax error         redirect_to :controller=>'protected',:action=>'admin' && return true

^ /var/www/rails/app/controllers/protected_controller.rb:17: syntax error         redirect_to :controller=>'protected',:action=>'roster' && return true

^ /var/www/rails/app/controllers/protected_controller.rb:19: syntax error         redirect_to :controller=>'main',:action=>'login' && return true

^ Although it doesn't look that way in what I pasted into this message, the '^' actually marks the end of the line. I sure don't see anything wrong with your syntax. In any event, hopefully I'm headed in the right direction now. I just need to figure out what the problem is with that syntax. Thanks.

         ... doug

Sorry, I should have paid more attention...seems to be a theme today.
You need to parenthesize the arguments to redirect_to so it's not ambiguous. It also appears that anding return true throws an error. I typically just do && return, but I am not sure if the nil return value will solve your issue. So try:

redirect_to(:controller=>'protected',:action=>'admin') && return

If that doesn't work, tru

when 'admin'     redirect_to(:controller=>'protected',:action=>'admin')     return true when ...

Sorry for the problems. I typically test my answers in irb, but sometimes I get lazy :slight_smile:

doug wrote:

You need to parenthesize the arguments to redirect_to so it's not ambiguous.

You know, I thought about that and actually tried adding the parenthesis. It didn't help. The reason I didn't mention it was that I looked it up in the 'Method Arguments' section of 'Programming Ruby -- The Pragmatic Programmer's Guide'. Those guys are pretty darn thorough. However, they make no mention of there being situations where parenthesis must be added to clarify what might otherwise be an ambiguity. So, I just concluded that Ruby must be even smarter than I thought. Anyway, as I say, it didn't work. I get the same syntax error problem. I might add that this parenthesis-not-required-with- methods thing is one of the bigger hurdles that I'm trying to get over in adjusting to Ruby. I'm still frequently finding myself saying, "Oh, that's a method!"

As far as putting the "return true" on a succeeding line goes, that takes me back to our old redirecting-in-a-way-that-never-completes Firefox error. So, I guess that I still don't have a workable solution for this. Thanks for the input though.

      ... doug

You know, I really should have thought of this earlier. I must really be asleep. Here is the problem. You are using that authenticate method as a before filter in your controller, but you are always redirecting or returning false! So what you need to do is this:

`class ProtectedController < ApplicationController

before_filter :accessControl

def roster

end

def logout

end

Actually, this is better (remove return true from the else so that it will return false and redirect to the login screen) :

` def accessControl

case session[:rank]

  when "admin"

    return true

  when "user"

    return true if params[:controller] == 'protected' &&

params[:action] == ‘roster’

  else

    redirect_to :controller=>'main',:action=>'login'

end

return false

end `

William Pratt wrote:

Not to beat a dead horse, but this version is better yet as it will redirect “user” to the appropriate action if they try the wrong action:

` def accessControl

case session[:rank]

  when "admin"

    return true

  when "user"

    return true if params[:controller] == 'protected' &&

params[:action] == ‘roster’

    redirect_to :controller => 'protected', :action =>

‘roster’

  else

    redirect_to :controller=>'main',:action=>'login'

end

return false

end `

William Pratt wrote:

Just FYI, I finally got this thing to work. Thanks to the list and especially to Bill for all of the superb help. I'm appending the code for my working 'protected' controller. Turns out to be pretty simple, huh? Thanks again.

class ProtectedController < ApplicationController

  before_filter :accessControl

  def roster   end

  def admin   end

  def logout   end