为什么这个验证示例不起作用?

时间:2014-05-06 01:22:26

标签: ruby-on-rails ruby

在Michael Hartl的Ruby on Rails教程中,我们目前正在创建一个user创建表单。我们需要验证电子邮件是否唯一。我们已经使用validates :uniqueness这样做了。然后他提到了以下内容:

使用验证:唯一性不保证唯一性。

  

D'哦!但是什么可能出错?这是:

     
      
  1. Alice注册示例应用程序,地址为alice@wonderland.com。
  2.   
  3. Alice意外点击“提交”两次,快速连续发送两个请求。
  4.   
  5. 发生以下序列:请求1在内存中创建通过验证的用户,请求2执行相同的操作,请求1   用户被保存,请求2的用户被保存。
  6.   
  7. 结果:两条用户记录具有完全相同的电子邮件地址,尽管有唯一性验证。
  8.   

“如果以上序列看起来难以置信,请相信我,它不是:它可以在任何具有大量流量的Rails网站上发生。幸运的是,解决方案很容易实现;我们只需要在数据库级别强制执行唯一性我们的方法是在电子邮件列上创建数据库索引,然后要求索引是唯一的。“

如果我没弄错,在rails尝试保存对象后,是否会进行验证检查?由于对象1首先保存,对象2不应该保存?

他还声称“我们只需要在数据库级别强制执行唯一性”,方法是在电子邮件列上创建“数据库索引”,然后检查它。为什么在电子邮件检查没有的时候这样做,我觉得好像他们没有任何不同。

1 个答案:

答案 0 :(得分:1)

使用唯一性验证保存记录将发出两个SQL请求:

  • 一个数据库,以确保不存在唯一值(即。alice@wonderland.com
  • 然后一个保存记录,如果所有验证都成功。

如果在第一个和第二个查询之间,其他人尝试使用该电子邮件地址注册,会发生什么?如果您有一个在多个进程中运行的繁忙站点,许多请求可能同时发生,因此这是一个看似合理的场景。

  • 第一个请求检查alice@wonderland.com是否存在 - 它不存在,因此验证通过。
  • 第二个请求检查alice@wonderland.com是否存在 - 它不存在,因此验证通过。
  • 然后第一个请求保存其记录。一切都好。
  • 然后第二个请求保存其记录。哦,现在数据库中有两个Alices!

如果还存在数据库约束,则第二个请求将无法保存其记录,即使验证成功。