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
...