Rails 4 HABTM自定义validation关联

我有一个简单的场景,但我似乎无法找到适用于Rails 4的任何建议的解决方案。我想简单地添加一个自定义validation器来检查我的HABTM关联之间存储的关联量。 更容易说和完成,令我惊讶?

我已经搜索了一个解决方案,但最终只得到了旧版本Rails的答案。 我有以下内容:

class User  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的原因是因为据我所知,存储的关联在添加之后首先可用。 我也尝试编写自定义validation器(例如, validate: :can_only_have_one_role ),但这也不起作用。

我以下面的方式添加关联,并在rails控制台中完成此操作(应该可以正常工作?):

 user.roles << role 

然而,它为用户添加了多个角色,并不关心任何类型的validation。

非常感谢,谢谢!

user.roles << role不对user执行validation。 用户很大程度上没有参与。 所有这一切都是在您的加入表中插入一条新记录。

如果你想强制用户只有一个角色,你有两个选择,都涉及丢弃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执行validation。

 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