gpt4 book ai didi

ruby-on-rails - 确保 has_many :through association is unique on creation

转载 作者:行者123 更新时间:2023-12-02 17:18:11 24 4
gpt4 key购买 nike

如果您在记录创建时保存一个 has_many :through 关联,您如何确保该关联具有唯一对象。唯一性由一组自定义属性定义。

考虑:

 class User < ActiveRecord::Base
has_many :user_roles
has_many :roles, through: :user_roles

before_validation :ensure_unique_roles

private
def ensure_unique_roles
# I thought the following would work:
self.roles = self.roles.to_a.uniq{|r| "#{r.project_id}-#{r.role_id}" }
# but the above results in duplicate, and is also kind of wonky because it goes through ActiveRecord assignment operator for an association (which is likely the cause of it not working correctly)

# I tried also:
self.user_roles = []
self.roles = self.roles.to_a.uniq{|r| "#{r.project_id}-#{r.role_id}" }

# but this is also wonky because it clears out the user roles which may have auxiliary data associated with them
end
end

根据关联的任意条件验证 user_roles 和角色是否唯一的最佳方法是什么?

最佳答案

最好的方法是在 user_roles 上创建一个唯一的多列索引,尤其是当您使用关系数据库时。

add_index :user_roles, [:user_id, :role_id], 唯一: true

然后在角色添加失败时优雅地处理:

class User < ActiveRecord::Base
def try_add_unique_role(role)
self.roles << role
rescue WhateverYourDbUniqueIndexExceptionIs
# handle gracefully somehow
# (return false, raise your own application exception, etc, etc)
end
end

关系数据库旨在保证引用完整性,因此请将其用于此目的。任何 ruby​​/rails-only 解决方案都会有竞争条件和/或非常低效。

如果您想提供用户友好的消息传递并勾选“以防万一”,请继续检查:

already_has_role = UserRole.exists?(user: user, role: prospective_role_additions)

不过,当您尝试持续添加角色时,您仍然必须处理潜在的异常。

关于ruby-on-rails - 确保 has_many :through association is unique on creation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45112151/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com