if __name__ is None
if __name__ is None

Reputation: 11533

Google Chrome - Prevent form resubmission on refresh in Rails app

I am new to Rails3, and I'm building very simple app (in which I don't want AJAX). Anyway, I have the index and create actions. The index action contains form:

<%= form_for @message, url: promote_index_path do |f| %>
 ...
<% end %>

My promote_controller looks like this:

  def index
    @message = Message.new url: @last_video, message_body: @last_message
  end

  def create
    @message = current_user.messages.new(params[:message])
    @message.get_video_id
    if @message.save
      redirect_to promote_index_url, flash: {notice: "Promotion has been started"}
    else
      render 'index'
    end
  end

This all works fine, except for when form is submitted successfully, and notice is flashed, if user hits F5, the form resubmits itself. Which should not be the case, since I am doing redirect_to after successful save. I believe I am doing something fundamentally wrong here, so please help me out.

EDIT: Here is my routes.rb

 resources :home
  resources :find
  resources :promote
  resources :settings
  root to: 'home#index'
  match 'auth/:provider/callback', to: 'sessions#create'
  match 'auth/failure', to: redirect('/')
  match 'logout', to: 'sessions#destroy', as: 'logout'
  match 'find', to: 'find#index', as: 'find'
  match 'promote', to: 'promote#index', as: 'promote'
  match 'settings', to: 'settings#index', as: 'settings'

And here is my rake routes

Jans-MacBook-Pro-2:tp3 jan$ rake routes
settings_index GET    /settings/index(.:format)          settings#index
    home_index GET    /home(.:format)                    home#index
               POST   /home(.:format)                    home#create
      new_home GET    /home/new(.:format)                home#new
     edit_home GET    /home/:id/edit(.:format)           home#edit
          home GET    /home/:id(.:format)                home#show
               PUT    /home/:id(.:format)                home#update
               DELETE /home/:id(.:format)                home#destroy
    find_index GET    /find(.:format)                    find#index
               POST   /find(.:format)                    find#create
      new_find GET    /find/new(.:format)                find#new
     edit_find GET    /find/:id/edit(.:format)           find#edit
          find GET    /find/:id(.:format)                find#show
               PUT    /find/:id(.:format)                find#update
               DELETE /find/:id(.:format)                find#destroy
 promote_index GET    /promote(.:format)                 promote#index
               POST   /promote(.:format)                 promote#create
   new_promote GET    /promote/new(.:format)             promote#new
  edit_promote GET    /promote/:id/edit(.:format)        promote#edit
       promote GET    /promote/:id(.:format)             promote#show
               PUT    /promote/:id(.:format)             promote#update
               DELETE /promote/:id(.:format)             promote#destroy
      settings GET    /settings(.:format)                settings#index
               POST   /settings(.:format)                settings#create
   new_setting GET    /settings/new(.:format)            settings#new
  edit_setting GET    /settings/:id/edit(.:format)       settings#edit
       setting GET    /settings/:id(.:format)            settings#show
               PUT    /settings/:id(.:format)            settings#update
               DELETE /settings/:id(.:format)            settings#destroy
          root        /                                  home#index
                      /auth/:provider/callback(.:format) sessions#create
  auth_failure        /auth/failure(.:format)            :controller#:action
        logout        /logout(.:format)                  sessions#destroy
          find        /find(.:format)                    find#index
       promote        /promote(.:format)                 promote#index
      settings        /settings(.:format)                settings#index

EDIT: The issue seems to be in Google Chrome.

Upvotes: 2

Views: 2212

Answers (2)

Ryann Graham
Ryann Graham

Reputation: 8209

I had the same problem and eventually tracked it down to a bug in Chrome (https://code.google.com/p/chromium/issues/detail?id=177855)

The work around I used is just to add some get parameters. Here's how I dealt with both the bug and the frustration. The result may not be appropriate for all scenarios. Fortunately my app is internal.

def create
  @message = current_user.messages.new(params[:message])
  @message.get_video_id
  if @message.save
    flash[:notice] = "Promotion has been started"
    redirect_to promote_index_url(chrome_bug_workaround: 177855)
  else
    render 'index'
  end
end

Another alternative is to create a collection route that is basically an alias for index.

In routes.rb:

match 'promote/all' => 'promote#index', :as => 'all_promotions'

In promote_controller.rb:

def create
  @message = current_user.messages.new(params[:message])
  @message.get_video_id
  if @message.save
    redirect_to all_promotions_url, flash: {notice: "Promotion has been started"}
  else
    render 'index'
  end
end

As an aside, your find, promote, and settings match routes appear to be redundant with the resource routes' index actions.

Upvotes: 2

Catfish
Catfish

Reputation: 19304

Try changing your methods to this:

def index
    @message = Message.new url: @last_video, message_body: @last_message

    respond_to do |format|
      format.html
    end
  end

  def create
    @message = current_user.messages.new(params[:message])
    @message.get_video_id

    respond_to do |format|
      if @message.save
        format.html {redirect_to promote_index_url, notice: "Promotion has been started"}
      else
        render 'index'
      end
    end
  end

Upvotes: 0

Related Questions