Rails:由于按下后退按钮而防止重复插入并再次保存

想想一个简单的Rails脚手架应用程序,其中包含一个表单,用于通过“保存”按钮将记录添加到数据库中。 在“创建”操作之后,控制器重定向到“显示”操作,用户可以使用“编辑”链接编辑刚刚插入的记录。 到目前为止,这么简单。

但是,如果用户在创建记录后使用浏览器的后退按钮返回“新”操作,则浏览器会显示包含用户刚刚输入的值的表单。 现在他改变了一些值并再次按下“保存”。 他认为这会改变记录,但当然这会创造一个新记录。

防止此类重复条目的首选方法是什么? 我正在寻找一个通用的解决方案,可能基于cookie或JavaScript。

经过一些调查,我找到了一个基于cookie的合适解决方案。 这里是:

在控制器的“新”操作中,生成具有当前时间的时间戳,并将其作为隐藏字段呈现在表单中。 当用户提交表单时,此时间戳将返回到控制器的“创建”操作。 创建记录后,此时间戳存储在会话cookie中。 如果用户通过浏览器的后退按钮返回“新”表单,则会获得陈旧forms,这意味着其时间戳早于存储在cookie中的时间戳。 在创建记录之前检查这一点并导致出现错误消息。

这是控制器代码:

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 

这里的表单代码:

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

当我遇到同样的问题时,我创造了这个解决它的小gem。 当用户回击时,他被重定向到记录的edit_path ,而不是返回到new_path

https://github.com/yossi-shasho/redirect_on_back

你可以这样做:

 def create @user = User.new(params[:user]) if result = @user.save redirect_on_back_to edit_user_path(@user) # If user hits 'back' he'll be redirected to edit_user_path redirect_to @user end end 

您的模型validation将确保电子邮件地址等内容是独一无二的,但我认为这更多地是关于可用性和体验,而不是其他任何内容。

假设您正在谈论帐户创建表单。 首先,您的表单提交按钮应该说“创建帐户” ,而不仅仅是“提交”。 然后,根据是否成功,显示“帐户已成功创建”或“创建帐户时出错”等消息。 如果用户看到此消息,他们将知道发生了什么。

当然,你不能阻止某人按下后退按钮并再次进入,但你应该为大多数用例设计。 如果他们碰巧回击,他们会看到显示“创建帐户”的按钮。 您可能应该在页面上显示“请注册新帐户以开始使用”的其他文本。

只需我0.02美元。

会话或cookie可能会导致副作用。

我完全同意:如果有一种方法可以validation您的模型,那么这是防止重复记录的最安全的方法。

你仍然可以做两件事。 防止浏览器缓存:当用户单击后退按钮时,表单中的字段将显示为空。 单击时禁用“创建”按钮。

 = f.submit "Create", :disable_with => "Processing..." 

当您的用户按下后退按钮时,该按钮将被禁用。

您可以使用validation器确保不插入重复值。 在这种情况下, validates_uniqueness_of :field

例如,如果您想阻止用户使用相同的电子邮件地址,则可以在用户模型中添加以下代码。

 validates_uniqueness_of :email 

这将检查列中是否存在与您尝试惰性的条目相同的任何先前条目。 祝好运

基于@Georg Ledermann回答我做了一小段代码,用于重定向编辑路径,如果用户回击然后点击创建。

 #objects_controller.rb def new @object = Object.new @stale_form_check = Time.now.to_i end def create @object = Object.new(object_params) #function defined in application_controller.rb redirect_to_on_back_and_create(@object) end 

 #application_controller.rb private def redirect_to_on_back_and_create(object) if session[:last_stale].present? and session[:last_stale_id].present? and session[:last_stale].to_i == params[:stale_form_check].to_i redirect_to edit_polymorphic_path(object.class.find(session[:last_stale_id].to_i)), alert: "Este #{object.model_name.human} ya ha sido creado, puedes editarlo a continuación" else if object.save session[:last_stale] = params[:stale_form_check].to_i session[:last_stale_id] = object.id redirect_to object, notice: "#{object.model_name.human} Creado con éxito" else render :new end end end 

最后将@stale_form_check参数添加到表单中

 <%= hidden_field_tag :stale_form_check, @stale_form_check %> 

您总是可以在需要的地方抽象出这种方法,但是如果您在许多地方需要这种行为,这样就可以避免项目中的大量重复

希望它有助于下一个,我曾经使用redirect_on_back gem,但这次对我来说不起作用,这个gem使用的_usec param总是被重置,所以它无法在每次比较时进行比较需要

这对我有用。

您需要做两件事:在控制器中创建一个方法,并在“create”方法下的同一个控制器中添加一个条件语句。

1)您的方法应该返回该用户的该对象的总数。

EX:

def用户current_user.object.count结束

2)在’create’方法中添加条件语句。

例:

def create @object = Object.create(object_params)@ object.save if user == 0 redirect_to x_path end

我希望这有帮助!