Within Seekler, we have several actions that are only available to logged-in users. We wanted a general solution that would first redirect the user to login or create an account and then complete the action the user initially requested. The primary motivator for this was non-logged-in users clicking ‘create your own list’ on a Seekler list. If a user clicked this link, we wanted to allow them to login or register and then have the list creation action take place and return them to their newly created list. We had other cases of site actions, that also required being logged in, so I was hoping to find a simple way to do this across the site.
We use the acts_as_authenticated plugin (I know most people are now using restful_authentication, we haven’t switched yet), which relies on before_filters to verify users are logged in before using logged-in-only actions. I ended up just adding one line into that system that makes it simple to return the user to his or her previous action after logging in.
In a controller using acts_as_authenticated, there is normally a before_filter requiring authentication before any actions except the actions available to all visitors
before_filter :login_required, :except => [ :show, :list]
This means that on an action like :create the user will end up calling the login_required method in /lib/authenticated_system.rb. If you add the following line to that method, it will record the information you need to redirect the user back to the action they intended after they login.
def login_required username, passwd = get_auth_data self.current_user ||= User.authenticate(username, passwd) || :false if username && passwd session[:last_action] = request.env['REQUEST_URI'] unless logged_in? && authorized? # add this line! logged_in? && authorized? ? true : access_denied end
At this point, the filter will direct all non-logged-in users to your associated login failure action, in our case /account/login
In the login action, (after doing any other login specific code) you just have to redirect the user if they have :last_action set
def login # login stuff if session[:last_action] redirect_to session[:last_action] else redirect_to :controller => 'account', :action => 'index' end end
You can add a bunch of other things like ignoring certain actions you don’t want to forward the user to, or also return the user to wherever they were before clicking a login link, but this simple version gives the basic idea. Obviously this code is specifically for the acts_as_authenticated plugin, but it should be relatively easy to generalize this same sort of solution to work for any type of authentication that is in use on your Rails project.
If you want to see this in action, just visit a list like Best Charities on Seekler and click the ‘create your own list’ link in the top right.