【rails】关联的唯一性约束

rails中,通过has_many through建立的两个模型之间的关联是以模型存在的。
在实际使用中,我们往往会遇到需要使关联唯一的情况,例如用户之间的关注关系,你一般不会想要在关联表中存放两个相同的记录。
这时,在应用级(即model文件)中可以验证uniqueness,在scope选项中填入要关联的元素,即可实现在多个属性上的唯一性验证。
这里是以学生选课为例子,在我们的例子中,假设学生与课程之间的选课关系唯一(实际上可能还有重修,我们先不考虑)
user表示学生,course代表课程,那么我们可以在courses_users.rb中加入以下验证

validates :user_id, uniqueness: { scope: :course_id }

当然,course_id和user_id的位置可以对调。

但是这只是在应用级进行约束,只有用户进行更新数据时才会去验证。而当数据库中原本就有数据时,该验证将不起作用。
更严重的是,在并发访问时,该约束并不保证一致性。即如果两个请求都添加同一选课关系时(虽然在该例中不太可能,但我们仍要考虑),由于并行执行,就可能出现出现两个都保存成功。
这是因为在并发执行时,该表相当于临界资源,验证时两个请求可能同时去查询该表,此时表中没有重复数据,于是两者都发现满足约束,就插入了两个相同的数据。
解决的方法是在表上建立唯一性约束

一个比较好的解决方法是添加带唯一性约束的多值索引
在数据库迁移中:

add_index :course_user_associations,
              [:course_id, :user_id], unique: true, name: :unique_index

这里指定了index的name,这是因为默认的命名很容易超出字数限制。

你可能感兴趣的:(rails)