Rails一对一关系

14
我有以下内容:
class User < ActiveRecord::Base
  has_one :car, :class_name => 'Car', :foreign_key => 'user_id'

class Car < ActiveRecord::Base
  belongs_to :worker, :class_name => 'User', :foreign_key => 'user_id'

基本上这是用户和汽车之间的一对一关系。
我希望用户只能拥有一辆汽车。这意味着,如果他创建了一辆分配给他的汽车,他将无法创建第二辆。
如何实现这一点?

在这个网址 http://rubyonrailsthrissur.wordpress.com/2012/07/19/one-to-one-relation-in-rails/ 中,这是关于Rails中一对一关系最实用的解释。 - Montells
3个回答

23

实现这个目标的方法有几种。我建议在该表上创建一个复合键索引,以确保user_id在表中是唯一的。这将确保它只出现一次。在迁移中,您可以编写类似以下代码:

add_index(:cars, :worker_id, :unique => true)

第一个参数是表名(不要忘记这通常是类名称的复数形式)。字段名称排在第二位。唯一性约束为true将防止您插入多余的行。

注意:这是数据库级别的约束。如果由于验证未捕获此问题,它将抛出错误。

除此解决方案外,您还需要向Car模型本身添加验证。

validates_uniqueness_of :worker_id, message: "can not have more than one car"

你会看到类似“工人ID不能拥有超过一辆汽车”的错误。你很可能希望自定义此处的“工人ID”部分。请参考这篇文章,了解如何进行自定义。

当然,你不一定要进行数据库约束,但是如果其他人向数据库中插入数据,这是一个好主意。否则,从Rails的角度来看,你将拥有“无效”的数据。


16

1
为什么不在用户尝试添加汽车之前进行测试?
if worker.car
 raise "sorry buddy, no car for you"
else
 car = Car.create(user_id: worker.id)
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接