HABTM-- 唯一性约束
我有两个具有 HABTM 关系的模型 - 用户和角色。
- user - has_and_belongs_to_many :roles
- role - own_to :user
我想在联接(users_roles 表)中添加唯一性约束,表示 user_id 和 role_id 必须是唯一的。在 Rails 中,看起来像:
validates_uniqueness_of :user, :scope => [:role]
当然,在 Rails 中,我们通常没有模型来表示 HABTM 关联中的连接关系。
所以我的问题是添加约束的最佳位置在哪里?
I have two models with a HABTM relationship - User and Role.
- user - has_and_belongs_to_many :roles
- role - belongs_to :user
I want to add a uniqueness constraint in the join (users_roles table) that says the user_id and role_id must be unique. In Rails, would look like:
validates_uniqueness_of :user, :scope => [:role]
Of course, in Rails, we don't usually have a model to represent the join relationship in a HABTM association.
So my question is where is the best place to add the constraint?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以为联接表添加唯一性
,请参阅在连接表中,Rails 缺少组合键的最佳解决方法是什么?
那么您的数据库将引发异常,您必须处理该异常。
我不知道任何准备好在这种情况下使用 Rails 验证,但您可以添加自己的验证,如下所示:
我会默默地删除数据库调用并报告成功。
ActiveRecord::Rollback 在内部捕获但不会重新引发。
编辑
不要使用我添加自定义验证的部分。它有点有效,但还有更好的选择。
按照 @Spyros 在另一个答案中建议的方式使用
:uniq
关联选项:(此代码片段来自 Rails Guides v.3)。阅读 Rails Guides v 3.2.13 的外观for 4.4.2.19 :uniq
Rails Guide v.4 特别警告不要使用
include?
检查唯一性,因为可能存在竞争条件。关于为连接表添加索引的部分保留。
You can add uniqueness to join table
see In a join table, what's the best workaround for Rails' absence of a composite key?
Your database will raise an exception then, which you have to handle.
I don't know any ready to use rails validation for this case, but you can add your own validation like this:
I would just silently drop the database call and report success.
ActiveRecord::Rollback is internally captured but not reraised.
Edit
Don't use the part where I'm adding custom validation. It kinda works but there is better alternatives.
Use
:uniq
option on association as @Spyros suggested in another answer:(this code snippet is from Rails Guides v.3). Read up on Rails Guides v 3.2.13 look for 4.4.2.19 :uniq
Rails Guide v.4 specifically warns against using
include?
for checking for uniqueness because of possible race conditions.The part about adding an index to join table stays.
在 Rails 5 中,您需要使用
distinct
而不是uniq
另外,尝试这样做以确保唯一性
In Rails 5 you'll want to use
distinct
instead ofuniq
Also, try this for ensuring uniqueness
我认为使用 :uniq => true 将确保您不会获得重复的对象。但是,如果您想在将第二个副本写入数据库之前检查是否存在重复项,我可能会使用 find_or_create_by_name_and_description(...)。
(当然名称和描述是您的列值)
I think that using :uniq => true would ensure that you get no duplicate objects. But, if you want to check on whether a duplicate exists before writing a second one to your db, i would probably use find_or_create_by_name_and_description(...).
(Of course name and description are your column values)
我更喜欢
其他选项参考此处
I prefer
other options reference here