我有一个简单的场景,但我似乎找不到任何适用于 Rails 4 的建议解决方案。我只想添加一个自定义验证器来检查我的 HABTM 关联之间存储的关联数量。说起来容易做,令我惊讶的是?
我已经寻找了一个解决方案,但似乎只得到了旧版本 Rails 的答案。我有以下几点:
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
after_save :check_maximum_number_of_roles
.
.
.
private
def check_maximum_number_of_roles
if self.roles.length > 3
errors.add(:roles, 'Users can only have three roles assigned.')
return false
end
end
end
class Role < ActiveRecord::Base
has_and_belongs_to_many :users
end
我使用的原因
after_save
是因为据我所知,存储的关联在添加后首先可用。我也尝试编写自定义验证器(例如 validate: :can_only_have_one_role
),但这也不起作用。我按以下方式添加关联,并在 rails 控制台中完成此操作(应该可以正常工作?):
user.roles << role
尽管如此,它为用户添加了多个角色,并且不关心任何类型的验证。
非常感谢帮助,谢谢!
最佳答案
user.roles << role
不对 user
执行验证.用户基本上不参与。所有这些都是在您的连接表中插入一条新记录。
如果你想强制一个用户只有一个角色,你有两种选择,都涉及扔掉 has_and_belongs_to_many
,你真的不应该再使用它了。 Rails 提供 has_many :through
,这一直是处理多对多关系的首选方式。
因此,第一种(我认为最好的)方法是使用 has_many
/belongs_to
.这就是在 Rails 中建模一对多关系的方式。应该是这么简单:
class Role
has_many :users
end
class User
belongs_to :role
end
第二种方法对于强制执行单个关联记录过于复杂,是创建您的连接模型,将其命名为
UserRole
,使用 has_many :through
,并在 UserRole
中执行验证.class User
has_many :user_roles
has_many :roles, through: :user_roles
end
class UserRole
belongs_to :user
belongs_to :role
# Validate that only one role exists for each user
validates :user_id, uniqueness: { scope: :role_id }
# OR, to validate at most X roles are assigned to a user
validate :at_most_3_roles, on: :create
def at_most_3_roles
duplicates = UserRole.where(user_id: user_id, role_id: role_id).where('id != ?', id)
if duplicates.count > 3
errors.add(:base, 'A user may have at most three roles')
end
end
end
class Role
has_many :user_roles
has_many :users, through: :user_roles
end
关于ruby-on-rails - Rails 4 HABTM 自定义关联验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24559489/