Im trying to redirect the user after the sign up by saving the referer in case when user came to sign up through clicking on any specific page. But its not working properly.
In my app controller
def save_referer
unless user_signed_in?
unless session['referer']
session['referer'] = request.referer || 'none'
end
end
end
In user model
def save_with(referer)
referer = referer unless referer == "null"
self.save
end
Here im saving it
if current_user.sign_in_count <= 1
if current_user.save_with(session[:referer])
redirect_to session[:referer]
else
redirect_to any_other
end
In User model, I guess you are not explicitly referring the attribute correctly.
def save_with(referer)
self.referer = referer unless referer == "null"
self.save
end
Generally, I take this strategy:
Anywhere I have a signup button I link to signup like so:
Signup!
Then in my signup's Action I do this:
def signup
session[:signup_refer] = params[:signup_refer] if params[:signup_refer] # put the refer in a session
redirect_to(signup_path) if session[:signup_refer] && params[:signup_refer] # this clears params if you want to keep your url nice an clean for the user
# do signup stuffs
signup_refer = session[:signup_refer] # get the refer info in a variable
session[:signup_refer] = nil # clear the session before redirecting
redirect_to(signup_refer ? signup_refer : "/default_post_signup")
end
I know it could be messy, but it totally works for me (well works in Merb, where it's "redirect() not redirect_to()) but you get the idea.
Related
I have overriden Devise's sign out path and made it request.referer. The problem with that is if the user is on a page which has the authenticate_user! before filter applied, I am sent to the sign in page and shown an error. This is not ideal, and I would like to redirect to the root_path ONLY when the user is coming from a path which has authentication requirements. What is the best way to do this?
I ended up inspecting the callbacks for the controller that the referrer url is associated with. If there are any authenticate_*! callbacks, they are each inspected to see if there are any actions specified in the #if instance variable. If there are none, the callback is applied to all of the actions and we know that the referring url is from a restricted action. If there are actions specified, we use regex to check if the referring action is restricted or not.
Any of the callbacks which meet the criteria are added to an array. After looping through the callbacks, we check if that array is empty. If it is, we send the user back to request.referer. If it is not empty, that means that sending them to request.referer will redirect them to the sign in page and show an error. In that case, we send the user to root_path.
If anything raises an error, the user is sent to root_path.
Here is the code:
def after_sign_out_path_for(resource_or_scope)
begin
controller_name = Rails.application.routes.recognize_path(request.referer)[:controller]
controller_class = "#{controller_name}_controller".camelize.constantize
authentication_callbacks = controller_class._process_action_callbacks.select { |callback| callback.filter.match /authenticate_\w+!/ }
action_name = Rails.application.routes.recognize_path(request.referer)[:action]
restricting_callbacks = []
authentication_callbacks.each do |callback|
callback_scope = callback.instance_variable_get(:#if)
if callback_scope.empty? || callback_scope.first.match(/action_name\s==\s(\'|\")#{Regexp.quote(action_name)}(\'|\")/)
restricting_callbacks << callback
end
end
restricting_callbacks.empty? ? request.referer : root_path
rescue Exception => e
request.referer
end
end
App has a lot of tests, and issue is that only authenticated users can view them. So when there are not, app redirects them to sing_in/login_as_guest page. For example user sings in or logs in as guest, after that I want to redirect them to the page they were actually going to.
But I have no idea from where to begin, and is this possible?
Can you please give me a key from where to begin?r
Here's an example:
class UserController < ApplicationController
def login
if User.authenticate(params[:user][:email], params[:user][:password])
referer = params[:referer] || session[:referer] || request.referer
flash.notice = 'Login succeeded'
redirect_to referer || root_path
else
flash.alert = 'Login failed'
redirect_to user_login_path
end
end
end
Now when you want to redirect back from somewhere, just add a referer path to either a param, the session or the request, and it will redirect back on success.
the end of chapter 5 and chapters 6,7,8,9 are step by step guide of what you need exactly
rails tutorial
Ok, I found the simple solution, works pretty well for me. Application controller:
if #current_permission.allow?(params[:controller], params[:action])
return true
else
redirect_to root_url
session[:was_going]=request.path #here I start session if request causes redirection
end
end
This method returns that request, if it exists
def root_or_request
if session[:was_going]
path=session[:was_going]
session[:was_going] = nil
return path
else
return root_url
end
end
And than after starting session I just redirect with calling this method.
On a rails 2.3.8 site I have login links on each page (that takes a user to a separate signin page). After a successful login the user is currently redirected to root. Instead I'd like to redirect to the page they were previously viewing.
I've tried using request.referer:
redirect_back_or_default(request.referer)
Where redirect_back_or_default:
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
But that generates an "access denied" error, even though the login is successful.
Instead of trying to redirect to the referrer, I would set the session[:return_to]
You'll need a before filter that runs before your authentication on all your actions:
def store_return_to
session[:return_to] = request.url
end
Then change your redirect to just be
redirect_back_or_default()
Before all you must store your url by cookies:
cookies[:return_to_url] = request.url
And then after success logging:
redirect_to cookies[:return_to_url] || root_path
cookies[:return_to_url] = nil
# or even better code in one line:
redirect_to cookies[:return_to_url].delete || root_path
https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html
I have a page that lists all of the projects that has sortable headers and pagination.
path:
/projects?order=asc&page=3&sort=code
I choose to edit one of the projects
path:
projects/436/edit
When I click save on that page, it calls the projects controller / update method. After I update the code I want to redirect to the path that I was on before I clicked edit a specific project. In other words, I want to be on the same page with the same sorting.
I saw link_to(:back) and thought that :back may work in redirect_to(:back), but that's a no go.
puts YAML::dump(:back)
yields the following:
:back
How can I get this to work?
In your edit action, store the requesting url in the session hash, which is available across multiple requests:
session[:return_to] ||= request.referer
Then redirect to it in your update action, after a successful save:
redirect_to session.delete(:return_to)
Why does redirect_to(:back) not work for you, why is it a no go?
redirect_to(:back) works like a charm for me. It's just a short cut for
redirect_to(request.env['HTTP_REFERER'])
http://apidock.com/rails/ActionController/Base/redirect_to (pre Rails 3) or http://apidock.com/rails/ActionController/Redirecting/redirect_to (Rails 3)
Please note that redirect_to(:back) is being deprecated in Rails 5. You can use
redirect_back(fallback_location: 'something') instead (see http://blog.bigbinary.com/2016/02/29/rails-5-improves-redirect_to_back-with-redirect-back.html)
I like Jaime's method with one exception, it worked better for me to re-store the referer every time:
def edit
session[:return_to] = request.referer
...
The reason is that if you edit multiple objects, you will always be redirected back to the first URL you stored in the session with Jaime's method. For example, let's say I have objects Apple and Orange. I edit Apple and session[:return_to] gets set to the referer of that action. When I go to edit Oranges using the same code, session[:return_to] will not get set because it is already defined. So when I update the Orange, I will get sent to the referer of the previous Apple#edit action.
This is how we do it in our application
def store_location
session[:return_to] = request.fullpath if request.get? and controller_name != "user_sessions" and controller_name != "sessions"
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
end
This way you only store last GET request in :return_to session param, so all forms, even when multiple time POSTed would work with :return_to.
In rails 5, as per the instructions in Rails Guides, you can use:
redirect_back(fallback_location: root_path)
The 'back' location is pulled from the HTTP_REFERER header which is not guaranteed to be set by the browser. Thats why you should provide a 'fallback_location'.
request.referer is set by Rack and is set as follows:
def referer
#env['HTTP_REFERER'] || '/'
end
Just do a redirect_to request.referer and it will always redirect to the true referring page, or the root_path ('/'). This is essential when passing tests that fail in cases of direct-nav to a particular page in which the controller throws a redirect_to :back
For those who are interested, here is my implementation extending MBO's original answer (written against rails 4.2.4, ruby 2.1.5).
class ApplicationController < ActionController::Base
after_filter :set_return_to_location
REDIRECT_CONTROLLER_BLACKLIST = %w(
sessions
user_sessions
...
etc.
)
...
def set_return_to_location
return unless request.get?
return unless request.format.html?
return unless %w(show index edit).include?(params[:action])
return if REDIRECT_CONTROLLER_BLACKLIST.include?(controller_name)
session[:return_to] = request.fullpath
end
def redirect_back_or_default(default_path = root_path)
redirect_to(
session[:return_to].present? && session[:return_to] != request.fullpath ?
session[:return_to] : default_path
)
end
end
link_to 'get me back', :back
The symbol :back is your swiss army knife.
I wonder if this will work
def edit
if request.referer != request.original_url
#return_here = request.referer
end
end
and use #return_here as a hidden value in the submit form.
of course reloading will kill this so just go back to a default fall back as needed.
I have a RoR application that's using the RESTful Authentication plug-in. Everything works great. I recently enabled cookie based authentication and that works fine too. The problem is that I want to change the default landing page when the user is authenticated using a cookie. I want to have a cookie authenticated user redirected to the same page they are redirected to upon successful login from the login form. They are always directed to the original request URL. I'm racking my brain on this as I thought I understood how it works and every change I make seems to have no impact.
I suspect this is something simple but I'm obviously missing it. I'd appreciate any feedback, guidance or suggestions you might offer.
I solved the problem but it's a bit ugly in my opinion. Here's what I did.
In the cookie authentication method I set a session variable indicating the cookie login method was used.
def login_from_cookie
user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token])
if user && user.remember_token?
session[:cookie_login] = true **# this is my addition**
self.current_user = user
handle_remember_cookie! false # freshen cookie token (keeping date)
self.current_user
end
end
Then in the :before_filter set_current_user I just check for that variable and redirect if it is set making sure to set the variable to nil.
def set_current_user
Authorization.current_user = current_user
if session[:cookie_login]
redirect_to :controller => :users, :action => :search
session[:cookie_login] = false
end
end
It's not pretty but it does work. I'm definitely open to any suggestions about how to clean this up.
You could add this line to the session controller after a successful login:
redirect_to :controller => 'dashboard', :action => 'index'
I'm using Bort so maybe this isn't part of Restful_Authentication itself but there is a successful_login method in the sessions controller that uses this restful_auth method:
redirect_back_or_default( root_path )
which is in defined in authenticated_system.rb
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
Can't you just have your routes setup so that
map.root :controller => :users, :action => :search
And then have a before_filter that checks to make sure that some "logged in" parameter is set? This param would just need to be set whenever the user logs in, either via cookie or via normal means. Then, whether the cookie authentication happens or normal auth happens, it will go to the default page. Maybe I'm misunderstanding the problem.
Restful Authentication stores the original URL that was trying to be accessed when the request is made. All of you have to do is prevent it from storing that value OR clear that value when a cookie authentication is performed and then the user will get redirected back to your default page.
I would probably do it like this in authenticated_system.rb
def login_from_cookie
user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token])
if user && user.remember_token?
self.current_user = user
session[:return_to] = nil # This clears out the return value so the user will get redirected to the default path
handle_remember_cookie! false # freshen cookie token (keeping date)
self.current_user
end
end
The is session[:return_to] = nil
Then just make sure you have set your default path in your sessions controller and you should be all set. The code in your sessions controller should be something like this:
redirect_back_or_default(the_path_you_want_to_send_them_to)