Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
735 views
in Technique[技术] by (71.8m points)

browser - Rails: Prevent duplicate inserts due to pressing back button and save again

Think about a simple Rails scaffold application with a "new" action containing a form to add records to a database with a "save" button. After the "create" action the controller redirects to the "show" action, where the user can use the "edit" link to edit the just inserted record. So far, so simple.

But if the user instead uses the browser's back button after creating a record to get back to the "new" action, the browser shows the form with the values the user just has entered. Now he changes some values and presses "save" again. He thinks that this would change the record, but of course this creates a new record.

What is the preferred way to prevent such duplicate entries? I'm looking for a general solution, maybe based on cookies or JavaScript.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

After some investigations I found a suitable solution based on cookies. Here it is:

In the controller's "new" action, a timestamp with the current time is generated and rendered in the form as hidden field. When the user submits the form, this timestamps gets back to the controller's "create" action. After creating the record, this timestamp is stored in the session cookie. If the user goes back to the "new" form via browser's back button, he gets a stale form, which means its timestamp is older than the one stored in the cookie. This is checked before creating the record and results in an error message.

Here is the controller code:

def new
  @post = Post.new
  @stale_form_check_timestamp = Time.now.to_i
end

def create
  @post = Post.new(params[:post])

  if session[:last_created_at].to_i > params[:timestamp].to_i
    flash[:error] = 'This form is stale!'
    render 'new'
  else
    @post.save!
    @stale_form_check_timestamp = Time.now.to_i
    session[:last_created_at] = @stale_form_check_timestamp
  end
end

And here the form code:

- form_for @post do |f|
  = tag :input, :type => 'hidden', :name => 'timestamp', :value => @stale_form_check_timestamp
  = f.input :some_field
  = .......

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...