Dodinas
Dodinas

Reputation: 6805

Rails 4 - Why Can't I Redirect After Save?

I am uploading several images (from http://localhost:3000/choices/new), which work fine, however, I am trying to redirect back to: http://localhost:3000/choices after it saves.

Here is my controller:

#app/controllers/choices_controller.rb
def create
 @choice = Choice.new(choice_params)
 @choice.filename = params[:filename].titleize
   if @choice.save
     respond_to do |format|
       format.html { redirect_to choices_path }
       format.json { head :no_content }
     end
   end
 end

In Rails Console, it outputs:

 Redirected to http://localhost:3000/choices
 Completed 302 Found in 58ms (ActiveRecord: 52.8ms)

Yet, the "new" page remains static. Any idea on how to correctly redirect this, perhaps with a flash message saying "Images uploaded succesfully"?

Thanks very much!

Upvotes: 3

Views: 2146

Answers (2)

Kowser
Kowser

Reputation: 11

This i similar to the above answer, but a little more versatile. It took some playing but I finally got it working, and I signed up for StackOverflow just so I could post an answer. Here is my solution (though I was using JS as my format)

respond_to do |format|
  format.html { redirect_to choices_path }
  @path = url_for(:controller => 'choices', :action => 'index')
  - or - choices_path for a named route
  format.js { render 'shared/redirect'}
  :flash => {:notice => "File Uploaded!"}
end

Now in your shared/redirect.js.erb file (notice this is a shared file, so you can reuse it):

#shared/redirect.js.erb
window.location.href = '<%= @path %>';

Upvotes: 0

Richard Peck
Richard Peck

Reputation: 76784

I only just learnt what asynchronous requests are, so I hope this helps...

If you're sending a 'background' request with JS, how can the controller affect your browser's viewport?

The controller is server-side, and is loaded every time you send a request. This means that unless your actual browser made an HTTP request directly to the controller, how can it cause a change in the view you have already rendered?

JS is client-side technology, which means that it can cause things to happen on your behalf, but its scope is limited to taking "DOM" elements & interacting with them.

I looked at some pretty informative answers in this regard, and found these ideas:

All of these answers say a similar thing: you need to handle the redirect with JS

Why not do something like this:

#app/controllers/choices_controller.rb
def create
 @choice = Choice.new(choice_params)
 @choice.filename = params[:filename].titleize
   if @choice.save
     respond_to do |format|
       format.html { redirect_to choices_path }
       format.json { render :json => {
          :location => url_for(:controller => 'choices', :action => 'index'),
          :flash => {:notice => "File Uploaded!"}
        }
     end
   end
 end

#assets/javascripts
$(document).ready(function() {
    $.ajax({
       success: function(data) {
           window.location = data.location
       }
    })
});

A much cleaner way to do it will be to send a plain JS request, and have this:

#/views/new.js.erb
window.location = <%= choices_path %>


#app/controllers/choices_controller.rb
def create
 @choice = Choice.new(choice_params)
 @choice.filename = params[:filename].titleize
   if @choice.save
     respond_to do |format|
       format.html { redirect_to choices_path }
       format.js
     end
   end
 end

Upvotes: 3

Related Questions