【问题标题】:Rails one-to-one relationshipRails 一对一关系
【发布时间】:2013-02-12 11:06:36
【问题描述】:

我有以下几点:

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'

它基本上是用户和汽车之间的一对一关系。

我想要的是让用户能够拥有一辆且只有一辆汽车。这意味着如果他创建分配给他的汽车,他将无法创建第二个。

这是怎么做到的?

【问题讨论】:

标签: ruby-on-rails ruby one-to-one


【解决方案1】:

稍微改变关系的定义:

class User < ActiveRecord::Base
  has_one :car

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

然后你就会确定你在寻找什么。见:http://guides.rubyonrails.org/association_basics.html#the-has-one-association

【讨论】:

    【解决方案2】:

    当然有几种不同的方法可以实现这一点。我建议在该表上创建一个复合键索引,以确保 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”部分。有关如何执行此操作的说明,请参阅此 post

    你当然不必做 db 约束,但万一其他人插入到 DB 中,这是个好主意。否则,就 Rails 而言,您将拥有“无效”数据。

    【讨论】:

      【解决方案3】:

      为什么不在用户尝试添加汽车之前进行测试?

      if worker.car
       raise "sorry buddy, no car for you"
      else
       car = Car.create(user_id: worker.id)
      end
      

      【讨论】:

        猜你喜欢
        • 2020-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多