views:

110

answers:

2

So I have a snazzy custom route for login

# routes.rb
map.login '/login', :controller => 'sessions', :action => 'new'

Visit www.asite.com/login and you're there. As is custom with failed login, however, we'll do the following in our action. Note what happens on failed login.

 # sessions_controller.rb

 def create
   self.current_user = User.authenticate(params[:email], params[:password])
   if logged_in?
     # some work and redirect the user
   else
     flash.now[:warning] = "The email and/or password you entered is invalid."
     render :action => 'new'
   end
 end

This is very typical. Simply render the new action and prompt for login again. Unfortunately you also get with it an ugly URL: www.asite.com/session. Ick! Is it possible to get rendering to respect the original URL?

A: 

Change render :action => 'new' to redirect_to login_path

Michael Sepcot
+7  A: 

Your problem is this: the user first visits /login and fills in the form. When they submit the form, they POST to /sessions, which is why the browser URL changes. To get around this you can do two things:

As Michael mentioned, you can redirect back to the :new action, changing the else to:

 else
   flash[:warning] = "The email and/or password you entered is invalid."
   redirect_to login_path
 end

Note that you'll need to change the flash so the message is available in the next request (following the redirect).

The second method is slightly hackier, but maybe worth mentioning. By using conditions on your routes, you can map both the login form (which is a GET) and the form submit (which is a POST) to the same path. Something like:

map.login '/login',
  :controller => 'sessions', :action => 'new', 
  :conditions => {:method => :get}

map.login_submit '/login',
  :controller => 'sessions', :action => 'create', 
  :conditions => {:method => :post}

Then if your form action is login submit path, things should work as you expect.

tomafro