Rails 3: How to "redirect_to" in Ajax call?
Solution 1
Finally, I just replaced
redirect_to(:controller => 'jobs', :action => 'index')
with this:
render :js => "window.location = '/jobs/index'"
and it works fine!
Solution 2
There is very easy way to keep the flash for the next request. In your controller do something like
flash[:notice] = 'Your work was awesome! A unicorn is born!'
flash.keep(:notice)
render js: "window.location = '#{root_path}'"
The flash.keep
will make sure the flash is kept for the next request.
So when the root_path
is rendered, it will show the given flash message. Rails is awesome :)
Solution 3
I think this is slightly nicer:
render js: "window.location.pathname='#{jobs_path}'"
Solution 4
In one of my apps, i use JSON to carry on the redirect and flash message data. It would look something like this:
class AccessController < ApplicationController
...
def attempt_login
...
if authorized_user
if request.xhr?
render :json => {
:location => url_for(:controller => 'jobs', :action => 'index'),
:flash => {:notice => "Hello #{authorized_user.name}."}
}
else
redirect_to(:controller => 'jobs', :action => 'index')
end
else
# Render login screen with 422 error code
render :login, :status => :unprocessable_entity
end
end
end
And simple jQuery example would be:
$.ajax({
...
type: 'json',
success: functon(data) {
data = $.parseJSON(data);
if (data.location) {
window.location.href = data.location;
}
if (data.flash && data.flash.notice) {
// Maybe display flash message, etc.
}
},
error: function() {
// If login fails, sending 422 error code sends you here.
}
})
Solution 5
Combining the best of all answers:
...
if request.xhr?
flash[:notice] = "Hello #{authorized_user.name}."
flash.keep(:notice) # Keep flash notice around for the redirect.
render :js => "window.location = #{jobs_path.to_json}"
else
...
Misha Moroshko
I build products that make humans happier. Previously Front End engineer at Facebook. Now, reimagining live experiences at https://muso.live
Updated on July 08, 2022Comments
-
Misha Moroshko almost 2 years
The following
attempt_login
method is called using Ajax after a login form is submitted.class AccessController < ApplicationController [...] def attempt_login authorized_user = User.authenticate(params[:username], params[:password]) if authorized_user session[:user_id] = authorized_user.id session[:username] = authorized_user.username flash[:notice] = "Hello #{authorized_user.name}." redirect_to(:controller => 'jobs', :action => 'index') else [...] end end end
The problem is that
redirect_to
doesn't work.How would you solve this ?
-
tokland over 11 yearsslightly slightly nicer:
render js: "window.location.pathname = #{jobs_path.to_json}"
-
mackmack over 11 yearsfinally, this only renders the view and ignores the controller code that redirect_to would execute.
-
Mindey I. about 11 yearsThis seems the best - would be nice to add a flash message in there also, but pretty nice.
-
Yarin over 10 years@mackmack - What do you mean? What controller code is getting ignored?
-
Jeff over 10 yearswouldnt this require an
eval
call on the client? -
zakelfassi over 10 yearsA better approach would be
render :js => "window.location = '#{jobs_path}'"
-
justinxreese almost 10 yearsIt works, but wouldn't it be a lot better to pass back the redirect location with an actual json success message and do the redirecting on the front end?
-
smudge over 9 yearsIsn't
jobs_path
basically as rigid as the URL? If the URL changes, so would the name of the route, unless you are being extra careful. Another alternative would berender js: "window.location = '#{polymorphic_path(@job.class)}'"
and use the calculated resourceful route based on the Job model. This only works if your routes are resourceful and use standard naming conventions that line up with your models. (Or if you specify model_name on your models so that they generate the right route names.) -
TheJKFever almost 9 yearsLots of good information here. Good and proper use of the render :location, of the :status option, and the xhr? check. As more web applications adopt APIs to serve mobile apps and the such, I hope to see things in this post become more standardized. Definitely have my upvote. Great Answer
-
Tasos Anesiadis over 7 yearsAwesome. Anyone has any idea why the the simple redirect_to does not work?
-
V. Déhaye over 7 yearsThanks for your answer, I used it. However, now for the testing, when I try to request this action as JS, it raises a CORS warning : ActionController::InvalidCrossOriginRequest. Do you have any idea of how to integrate this in tests ?
-
MSC over 5 years@Tasos Anesiadis, redirect_to doesn't work when the form is a 'remote' Rails form because the browser's been told to interpret the response from the controller as Javascript. You can see the redirect_to page in the Response tab (via the Network panel) of Chrome DevTools but what's needed instead is an instruction to the browser from the controller to go find a different page. The window.location solutions provided here, or changing the form to a regular 'local' form are required, unless you want to get into manually submitting and processing the form data via fetch() and JSON.