Jen*_*örk 6 validation activerecord ruby-on-rails has-and-belongs-to-many ruby-on-rails-4
我有一个简单的场景,但我似乎无法找到适用于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
Run Code Online (Sandbox Code Playgroud)
我使用的原因after_save是因为据我所知,存储的关联在添加后首先可用.我也试过写一个自定义验证器(例如validate: :can_only_have_one_role),但这也不起作用.
我以下面的方式添加关联,并在rails控制台中完成此操作(应该可以正常工作?):
user.roles << role
Run Code Online (Sandbox Code Playgroud)
然而,它为用户添加了多个角色,并不关心任何类型的验证.
非常感谢,谢谢!
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
Run Code Online (Sandbox Code Playgroud)
第二种方法是强制执行单个关联记录,它是创建您的连接模型,调用它UserRole,使用a 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3021 次 |
| 最近记录: |