【问题标题】:Rails - User Pressing 'Back' after object creation, Creating DuplicatesRails - 用户在创建对象后按“返回”,创建重复项
【发布时间】:2011-12-05 22:06:34
【问题描述】:

我遇到了一个问题,当用户填写我的评估表时,点击“创建”,然后点击浏览器的后退按钮,进行一些编辑,然后再次点击“创建”,它正在创建重复的评估。

防止此类事情发生的最佳方法是什么。

在创建时每个survey_criterion 应该只存在一个evaluation。我不希望用户在点击后退按钮、用新内容填写表单并再次单击“创建”后丢失他们输入的任何数据。

更新

routes.rb

resources :survey_criteria do
  resources :groups do
    resources :evaluations
  end
end

survey_criterion.rb

has_many :evaluations

评估.rb

belongs_to :survey_criterion
belongs_to :group

有更复杂的关联,但我正在寻找的答案更多,“当用户按下'返回'按钮,修改表单,然后再次点击创建时如何处理”。

我希望它更新我认为在这种情况下自动创建的那个,而不是向用户抛出错误。我知道我可以添加一个会出错的验证,但我希望它对我认为的用户不可见。

想法?

【问题讨论】:

  • 您能否更具体地说明两个模型之间的关系性质?关于你的create 行动?
  • 明天上班时,我会尝试添加更多信息。谢谢。
  • 获取有关您的表单的信息也可能很有用。您是创建关联的evaluation 和新的survey_criterium(以嵌套形式),还是以不同的形式创建两者?如果我很清楚你想要达到的目标,nested form 应该可以解决问题,因为点击后退按钮会让你回到新的survey_criterium 表单,确保如果你再次点击提交,你会尝试创建一个新的survey_criterium 而不是一个新的evaluation

标签: ruby-on-rails ruby-on-rails-3 browser duplicates back-button


【解决方案1】:

最简单的解决方案是更改 create 操作,它应该像下面的伪代码一样工作:

def create
  # ...
  if evaluation_exists?
    update_evaluation(params[:evaluation])
  else
    create_evaluation(params[:evaluation])
  end
  # ...
end

至于你的问题“当用户按下'返回'按钮,修改表单,然后再次点击创建时如何处理”,然后我使用一些随机令牌 (一个短字符串) 作为隐藏字段放置在表单中。

当创建请求到来时,我检查这个令牌是否已经存储在会话中。如果不是,那么我创建对象,并将该令牌添加到已使用的列表中。如果令牌已经存在于会话中,我知道用户刚刚重新提交了表单,我可以采取相应的行动。通常我会问他是否应该创建另一个对象。在会话中,我存储的令牌通常不超过 3-5 个。

看起来像这样(是的,这只是一个插图)

def create
  token = params[:token]
  session[:tokens] ||= []
  if session[:tokens].include? token
    render_the_form_again( "You have already created the object. Want another?" )
  else
    create_the_object
    session[:tokens] << token
  end
  # ...
end

【讨论】:

  • 感谢您花时间回答这个问题,它确实帮助我思考它,并且应该可以很好地满足我的需要。
  • 我认为如果有人在创建表单上使用后退按钮,他应该期望每次都创建一个新对象,这只是常识。另一方面,我承认@Arsen7 的解决方案更加用户友好
  • 我认为,如果有人在他们的创建表单中打错字,在没有意识到的情况下迅速回击,修正他们的错字并再次点击创建,那对他们来说不是“常识”。他们只会感到困惑,为什么它没有达到他们想要的效果。用户和常识并不完全混合:)
  • 在您的所有控制器中看起来都很棒。
【解决方案2】:

在您的评估模型中,添加以下行:

validates_uniqueness_of :survey_criterion_id

这是假设 SurveyCriterion 拥有与您的评估相关联的外键。

【讨论】:

  • 嗯,它可能比这更复杂一些。明天我回去工作的时候再谈这个。谢谢。
【解决方案3】:

你还可以做两件事:

  1. 阻止浏览器缓存。
  2. 使用 :disable_with => “处理”选项禁用“创建”按钮。

这里也有讨论:https://stackoverflow.com/a/12112007/553371

【讨论】:

    【解决方案4】:

    一种不太优雅但更通用的方法是使用history.pushState。创建后的页面:

    $(function(){
      if(history.pushState){
        window.onpopstate = function(event){
          if(window.history.state && window.history.state.previousStep){
            window.location = window.history.state.previousStep;
          }
        }
        window.history.replaceState({ previousStep: '#{edit_resource_url(resource)}'}, document.title, window.location);
        window.history.pushState({}, document.title, window.location);
      }
    
    })
    

    本示例使用 HTML5 的 History API。使用history.js 项目可以通过回退来完成类似的事情

    【讨论】:

      猜你喜欢
      • 2016-10-02
      • 2014-02-17
      • 2021-01-03
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 2014-07-07
      • 2015-04-22
      • 1970-01-01
      相关资源
      最近更新 更多