你在这里有两个问题:
- 您正在覆盖验证
- 保存中的操作顺序引起了问题。
您正在覆盖 validate 方法,这是一件坏事,因为内置行为会拒绝将具有验证错误的记录保存到数据库中。要添加您想要执行的自定义验证:
validate :maximum_group_length
def maximum_group_length
if self.groups.length > 5
self.errors.add(:groups, "cannot have more than 5 groups")
end
end
但是,HABTM 关系的性质要求您将其作为 after_save 回调。只是因为事情完成的顺序。user.groups
是基于隐式连接表的,在连接表更新之前不会更新。
如果您尝试将验证作为回调的一部分(before_save、after_creation 等),那么向对象添加错误不会触发回滚。回调只有在返回 false 时才会触发回滚。这将处理问题建议的保存后实施。
after_save :validate_maximum_group_length
def validate_maximum_group_length
if self.groups.length > 5
self.errors.add(:groups, "cannot have more than 5 groups")
return false
end
end
另一种解决方案是使用显式连接模型。还有一个 has_many :through 关系。连接模型的表在更新语句中更新。has_many :through 和 HABTM 关系在保存后更新关系。
class User < ActiveRecord::Base
has_many :user_groups
has_many :groups, :through => user_groups, allow_destroy
validate :max_group_length
errors.add(:groups, "cannot have more than 5 groups") if self.user_groups.length > 5
end
end
class UserGroup < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
class Group < ActiveRecord::Base
has_and_belongs_to_many :users
end
HABTM 隐式使用连接表,因此不需要在组端进行更改。
但是,您需要修改表单以更新表单以在 params 哈希中提供 group_id 为params[:user][:user_group_attributes][0][:group_id][3]