Rails - redirecting to previous page properly - ruby-on-rails

In my application I am trying to enforce that users be signed in to preform certain actions. And when they try to preform these actions when not signed, they are redirected to the 'Sign-In' page, and once they have signed in, they are redirected back to the page they were trying to access. I have all of this working properly with the below code.
Controllers Code
if !(signed_in?)
session[:return_to] = newcompany_path
redirect_to signin_path
flash[:notice] = "You must be signed in to add companies."
else
#company = Company.new
#primary_field = ##fields
end
...
redirect_path = session[:return_to]
if user && user.authenticate(params[:session][:password])
sign_in user
session[:return_to] = nil
if (redirect_path == nil)
redirect_to user
else
redirect_to redirect_path
end
else
The issue I am running into is, if the user clicks away from the sign-in page without actually signing in, the session[return_to] variable is not cleared properly, and if they then go back to sign in later, they are redirected to the wrong page.
So, how would I set it up so if the user clicks away from the sign-in page, the session[:redirect_to] variable is reset?

You could pass the return_to path in query string parameter rather than the session and submit it alongside the sign in form so that it only applies for that form, rather than subsequent requests.
When redirecting to the sign in form, it'd look like:
redirect_to signin_path(return_to: newcompany_path)
Then, in your sign in form, make sure to include a hidden field with the return_to value, like:
hidden_field_tag :return_to, params[:return_to]
Then in your controller action for signing in, you'll check params[:return_to] rather than session[:return_to] to get the path you want.

Is this what you're looking for?
redirect_to request.referrer

Related

How to get the referer url of a previous page in Rails 4

I will try to put it in a simple way. I have a Sign Up button (which redirects to /users/sign_up page) on /visitors/owner-faq page. I want the URL of this page(/visitors/owner-faq) after signing up so that i can use it to set something like
if sign_up_from_url == '/visitors/owner-faq'
#user.role = 'Owner'
end
I tried to use request.referer in the controller, but it gave me /users/sign_up not /visitors/owner-faq. However when I used <%= url_for(:back) %> in the sign up view page, it gave me /visitors/owner-faq which I want.But I cannot figure out how to access it in the controller. Can anyone suggest me how to access that value in controller? I'm using Devise for sign up.
What happens is if the user is on /visitors/owner-faq page and clicks on the sign up link, the referrer in the sign up page is /visitors/owner-faq. This is the reason why url_for(:back) works on that page. Now, after submitting the form in the sign up page, the referrer is now changed to the sign up url, which makes sense.
What you want to do is save the referrer in the session when the user visits the sign up page. So in the action that serves the sign up page (say that's the users new action)
class UsersController < ApplicationController
def new
session[:referrer] = request.referrer
end
end
So when the user submits the sign up form, you can access the session
def create
referrer = session.delete(:referrer)
user = User.new
user.role = 'owner' if referrer == '/visitors/owner-faq'
user.save!
end
Even you don't have to store in session
if request.referrer == sign_up_from_url
super
end
This will give you last referrer before sign_up_from_url.

Redirect from custom devise edit page

I am using devise for user registrations. I set up a custom edit page '/info' to use as an additional signup page. The only problem is after you submit the edits on the info page it redirects to the user profile. I am able to change it redirect to the home page (where I want after /info) but then it also redirects there from the normal edit page. I am not sure how to redirect based on what page the user is on.
My one idea was to get the users current path and use an if statement but I haven't been able to get that to work.
registrations_controller.rb:
def update
...
current_uri = request.env['PATH_INFO']
if current_uri == '/info'
redirect_to root_path, notice: "Welcome"
else
redirect_to user_path(#user)
end
end
Normally it just looks like this:
def update
...
redirect_to user_path(#user)
end
The problem seems to be you need to keep data around to determine where to redirect. A few ideas:
You could store data in the session when a user visits a previous page and check this data in your action to determine where to redirect the user. The session is often a convenient place to store things that are consistent between requests but that should not be persisted to the database.
You could store data in the database (for instance, add a flag to your user model) and check this to determine where to redirect.
You could check request.referer and redirect based on the value there. This may not be as reliable.

Can I redirect back after sign in, if link is from email (in Rails)?

I have implemented redirect_to_back method in my ApplicationController for users that are not signed in (from this blogpost:
def redirect_to_back_or_default(default = root_url)
if request.env["HTTP_REFERER"].present? and request.env["HTTP_REFERER"] != request.env["REQUEST_URI"]
redirect_to :back
else
redirect_to dashboard_url
end
end
and I'm using in sessions_controller#create:
if #user && #user.authenticate(params[:password])
sign_in(#user)
redirect_to_back_or_default(dashboard_url)
else
...
The problem is, this only works if the request is coming from the application and not if it is a direct link, like in an email.
Is there a solution for this?
I would recommend altering how you accomplish this. If you follow the flow below I think it will produce the results you're looking for:
User arrives at URL (either by clicking link in email or typing it or whatever) but is not yet authenticated.
Store the URL that the user is at in the session
Redirect to the sign-in controller/action
After authenticating the user look in the session for where you stored the arrival URL
If present redirect to that URL (and clear stored URL out of the session) otherwise redirect to dashboard_url (it won't be present if someone navigates directly to the sign-in controller/action).

Submit form after devise login

I'm trying to let users submit a reservation request without being logged in. After they submit unauthed users are prompted to sign in or sign up. After signing up I'd like the form to be submitted and the (new registered) users to be taken to the checkout page.
Store location keeps the last page to return users after logging in. I need to figure out how to continue users on their intended path by submitting their forms and placing them on the checkout page after sign up/ sign in.
def store_location
#stores the last url. Used for post-login redirects to what the user was trying to do last.
if (!request.fullpath.match("/users/") && !request.xhr?) # don't store ajax calls
session[:previous_url] = request.fullpath
end
end
Ok, I think this is pretty dirty but I haven't been able to find another way to do this.
after_sign_in_path_for is a method Devise calls that allows you to send people to different pages after sign in.
I took all the create logic out of the controller and put it into a service object.
def after_sign_in_path_for(resource)
if session[:booking_params].present?
#booking = Booking::CreateBooking.new(user:current_user, params: session[:booking_params]).return_booking
checkout_booking_path(#booking.public_id)
else
session[:previous_url] || root_path
end
end
In the controller, the create method is split into two parts. If there is no current user I save their params into the session and they are sent to login. If there is the CreateBooking service object is called normally.
def create
if current_user.nil?
session[:booking_params] = params
redirect_to new_user_registration_path
else
#booking = Booking::CreateBooking.new(user:current_user, params:params).return_booking
respond_to do |format|
format.html { redirect_to checkout_booking_path(#booking.public_id) }
end
end
end
In the after_sign_in_path_for method I check for the session params and create the booking there.
Let me know if there is a better way to do this!

Rails: Calling Devise authenticate_user! and handling invalid user/password exception

I have a popup that will only allow to view/save some information if the user is authenticated.
I am using devise.
In the controller before_filter it checks if user is signed in and if not, show a sign in page.
This sign in page is ripped down version of the site's sign in page, so that it fits nicely to the popup.
On the authenticate action I call authenticate_user!. Everything works fine when the user enters valid credentials. But when the credential is invalid, devise automatically redirects to site's sign in page (which as I stated is different and not fit for a popup)
I tried appending a rescue to the call, but to no avail.
Anyone could suggest a better/right way to do this please? :)
def authenticate
authenticate_user! rescue redirect_to "/popup/sign_in"
if user_signed_in?
respond_to do |format|
format.html {
flash[:notice] = I18n.t("logged_in_succesfully")
redirect_back_or_default(accounts_path)
}
else
flash[:error] = I18n.t("devise.failure.invalid")
render "/popup/sign_in"
end
end

Resources