Rails validates_uniqueness_of 的必要性?

iwinux · 发布于 2012年08月03日 · 最后由 xds2000 回复于 2012年08月03日 · 5045 次阅读
96

根据 Rails 官方文档 所说,假如 table 中某个 field 建立了 unique key index,那么插入重复值(比如重复的 email)时就会抛 ActiveRecord::RecordNotUnique 异常。这个重复值的检查是在数据库级别进行的。

与此同时,大家平时用的比较多的方法是 validates_uniqueness_of,其实现方式是在 model validation 阶段以 find by field 查询数据库中是否存在重复值。由于 validation 和最终写入存在时间差,在高并发的情况下这种 validation 很不可靠。(所以无论如何都必须捕捉 ActiveRecord::RecordNotUnique 异常?)

我的问题:

  1. 既然 validates_uniqueness_of 不可靠,为什么不省掉这一步,直接捕捉(可能会抛出的)ActiveRecord::RecordNotUnique 异常?

  2. 在什么地方处理这个异常比较合适(controller 还是 model)?最好能统一处理所有 model 的 ActiveRecord::RecordNotUnique 异常。

共收到 9 条回复
96

我也觉得直接丢给数据库比较好,但问题很可能是数据库只会报个IntegrityError,你不知道是哪(几)个Field重复导致的。我觉得即便如此也应该先INSERT,失败再去查询。

77

MVC 中 Model 的作用是让开发者尽可能“忘记” DB 的存在吧 而且 validates_uniqueness_of 还有 :if, :scope 等选项,可以更灵活

对于问题 2,我也期待好答案

这里还有一个对 ActiveRecord::RecordNotUnique 的讨论 http://www.ruby-forum.com/topic/3908828

8

我也觉得没有用,每次都会生成这样一条SQL:

SELECT 1 AS one FROM `users` WHERE `users`.`email` = xx LIMIT 1

不过,如果不加的话要自己对异常进行处理。

我的理解是,rails作为一个一栈式框架,做了很多没用的事儿。这可以使应用不依赖其他组件(数据库/反向代理/缓存容器等)就可以正常工作。但实际上需要用户自己去取舍,比如rails可以处理静态文件,但是几乎所有实际环境都交给nginx处理。

96

有关第一个问题,首先可以想到的是errors的输出更加方便吧。 关于第二个问题有个额外的疑问,是如果问题2有一个好的解决方案,能否完善一下ActiveRecord,由它负责捕获异常解决掉这个问题呢。

1

加个模型校验,做提交前的客户端校验比较方便。

8

我的观点是,数据库层面的唯一性一定要加。 model层的唯一验证看是否需要错误回显等应用逻辑去决定。

96

#4楼 @fleuria #5楼 @Rei #6楼 @hooopo

第一个问题按照大家的说法,应该是方便 form validation error messages 的显示。

第二个问题,也许在个别 controller 的 rescue_from 里面处理 ActiveRecord::RecordNotUnique 异常比较好?

1

#7楼 @iwinux 是的。短时间内发生冲突,算是小概率事件了,给个统一错误就好。除非是商场抢拍这样的操作,就个别处理。

202

我的思路是 ,没遇到问题,就不要去考虑。有问题,先测试,找出G点。再技术讨论,设计设计软件架构。

10楼 已删除
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册