gpt4 book ai didi

ruby-on-rails - 避免在 has_many :through 中重复的 Rails 习惯用法

转载 作者:行者123 更新时间:2023-12-03 07:50:50 25 4
gpt4 key购买 nike

我的 Rails 应用程序中的用户和角色之间存在标准的多对多关系:

class User < ActiveRecord::Base
has_many :user_roles
has_many :roles, :through => :user_roles
end

我想确保一个用户只能被分配一次任何角色。任何插入重复项的尝试都应忽略该请求,而不是抛出错误或导致验证失败。我真正想代表的是一个“集合”,插入一个已经存在于集合中的元素是没有效果的。 {1,2,3} U {1} = {1,2,3},而不是 {1,1,2,3}。

我意识到我可以这样做:
user.roles << role unless user.roles.include?(role)

或者通过创建一个包装方法(例如 add_to_roles(role) ),但我希望有一些惯用的方式通过关联使其自动化,这样我就可以写:
user.roles << role  # automatically checks roles.include?

它只是为我工作。这样,我就不必记得检查重复项或使用自定义方法。框架中是否有我遗漏的东西?我最初认为 has_many 的 :uniq 选项可以做到,但它基本上只是“选择不同”。

有没有办法以声明方式做到这一点?如果没有,也许通过使用关联扩展?

以下是默认行为如何失败的示例:

>> u = User.create
用户创建 (0.6ms) INSERT INTO "users"("name") VALUES(NULL)
=> #<用户名:3,姓名:nil>
>> u.roles << Role.first
角色负载 (0.5ms) SELECT * FROM "roles"LIMIT 1
UserRole 创建 (0.5ms) INSERT INTO "user_roles"("role_id", "user_id") VALUES(1, 3)
角色负载 (0.4ms) SELECT "roles".* FROM "roles"INNER JOIN "user_roles"ON "roles".id = "user_roles".role_id WHERE (("user_roles".user_id = 3))
=> [#<角色 ID:1,名称:“1”>]
>> u.roles << Role.first
角色负载 (0.4ms) SELECT * FROM "roles"LIMIT 1
UserRole 创建 (0.5ms) INSERT INTO "user_roles"("role_id", "user_id") VALUES(1, 3)
=> [# , # ]

最佳答案

只要附加的角色是一个 ActiveRecord 对象,你在做什么:

user.roles << role

应该为 :has_many 自动去重协会。

对于 has_many :through , 尝试:
class User
has_many :roles, :through => :user_roles do
def <<(new_item)
super( Array(new_item) - proxy_association.owner.roles )
end
end
end

如果 super 不起作用,您可能需要设置一个 alias_method_chain。

关于ruby-on-rails - 避免在 has_many :through 中重复的 Rails 习惯用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1315109/

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