validationhabtm关联的长度而不保存

我有一个与组有HABTM关系的用户模型。 我不希望用户能够在5个以上的组中,因此想要validationHABTM关系的长度。

在编辑用户页面上,我有一个复选框列表,用户可以在其中选择他们想要的组(我正在使用formtastic作为表单)。

在我的用户控制器中我打电话:

@user.update_attributes(params[:user]) 

这导致rails自动更新关联。

在我的用户模型中,我有以下内容:

 def validate if self.groups.length > 5 self.errors.add(:groups, "cannot have more than 5 groups") end end 

这导致表单validation失败,但update_attributes调用已更新数据库以反映对关联组的更改。 这样,每次用户单击“保存”按钮时,即使记录无效,也会保存其组关联。

解决这个问题的最佳方法是什么?

我想也许validation需要在组模型而不是用户模型上,这会起作用吗? 理想情况下,我想更新关联的组而不保存记录,进行validation,然后保存记录。

你有两个问题:

  1. 你是最重要的validation
  2. 保存中的操作顺序导致问题。

您正在覆盖validation方法,这是一件坏事,因为内置行为可以拒绝将带有validation错误的记录保存到数据库中。 要添加自定义validation,您需要执行以下操作:

 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基于隐式连接表,并且在更新连接表之前不会更新。

如果您尝试validation作为回调的一部分(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 

另一种解决方案是使用显式连接模型。 和a_many:通过关系。 连接模型的表在update语句中更新。 其中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]