假复合主键? 轨道

我有一个id为| patient_id | client_id | active的表。 记录是patient_id唯一的,client_id意味着每个客户每个患者应该只有一个登记。 通常我会把它作为主键,但在rails中我将id作为我的主键。

执行此操作的最佳方法是什么? validation?

听起来你有一个模型关系:

class Client < ActiveRecord::Base has_many :patients, :through => :enrollments has_many :enrollments end class ClientPatient < ActiveRecord::Base belongs_to :client belongs_to :patient end class Patient < ActiveRecord::Base has_many :clients, :through => :enrollments has_many :enrollments end 

要强制执行约束,我会在ActiveRecord中执行此操作,以便在尝试保存打破约束的记录时获得正确的反馈。 我只想修改你的ClientPatient模型:

 class Enrollment < ActiveRecord::Base belongs_to :client belongs_to :patient validates_uniqueness_of :patient_id, :scope => :client_id end 

但要小心,因为虽然这对于小规模应用程序非常有用,但它仍然容易出现如下所述的竞争条件: http : //apidock.com/rails/v3.0.5/ActiveRecord/Validations/ClassMethods/validates_uniqueness_of “并发”和诚信“

正如他们在那里描述的那样,您还应该为数据库中的表添加唯一索引。 这将提供两个直接的好处:

  • 基于这两个id的validation检查和通过该模型的任何搜索将执行得更快(因为它们被索引)
  • 唯一性约束将在DB端强制执行,并且在极少发生竞争条件时,您不会将错误数据保存到数据库中……尽管如果您没有捕获错误,用户将获得500服务器错误。

在迁移文件中添加以下内容:

 add_index :enrollments, [:patient_id, :client_id], :unique => true 

希望这有用:)

编辑(修复了一些命名问题和几个明显的错误):

然后很容易找到您正在寻找的数据:

 Client.find_by_name("Bob Smith").patients Patient.find_by_name("Henry Person").clients 

validation将起作用( 使用唯一索引备份它们! ),但是无法在vanilla Rails中获得真正的复合主键。 如果你想要一个真正的复合主键,你将需要一个gem /插件 – composite_primary_keys是我找到的,但我相信还有其他的。

希望这可以帮助!

在两列中为表添加UNIQUE约束。 以下是MySQL的参考资料http://dev.mysql.com/doc/refman/5.0/en/constraint-primary-key.html