本文介绍了在不保存的情况下验证habtm关联的长度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个与组具有HABTM关系的用户模型。我不希望用户能够超过5个组,因此想验证HABTM关系的长度。

I have a user model with a HABTM relationship to groups. I do not want a user to be able to be in more than 5 groups, so would like to validate the length of the HABTM relationship.

在编辑用户页面上,我有一个复选框列表,用户可以在其中选择要加入的组(我在表单中使用表格形式)。

On the edit user page I have a list of checkboxes where the user can select the groups they want to be in (I'm using formtastic for the form).

在我的用户控制器中,调用:

In my users controller I'm calling:

@user.update_attributes(params[:user])

这会导致rails自动更新关联。

which is causing rails to update the associations automatically.

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

In my user model I have the following:

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

这导致表单无法通过验证,但是update_attributes调用已经更新了数据库以反映对相关组的更改。这样,即使记录无效,每次用户单击保存按钮时,也会保存其组关联。

This is causing the form to fail the validation, but the update_attributes call has already updated the database to reflect the changes to the associated groups. This way every time a user clicks the save button their group associations are saved, even though the record is invalid.

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

What's the best way to solve this?

我认为也许验证需要在组模型而不是用户模型上进行,这行得通吗?理想情况下,我想在不保存记录的情况下更新关联的组,进行验证,然后保存记录。

I think perhaps the validation needs to be on the group model instead of the user model, would this work? Ideally I'd like to update the associated groups without saving the record, do the validation, and THEN save the record.

推荐答案

您在这里遇到两个问题:

You had two problems here:


  1. 您要覆盖验证

  2. 保存中的操作顺序

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

You're overwriting the validate method which is a bad thing, because the built in behaviour to deny records with validation errors to be saved to the database. To add custom validations you want to do this:

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 是基于隐式联接表的,在更新联接表之前,不会更新for。

However, the nature of HABTM relationships requires you to do it as an after_save callback. Just because of the order that things are done. user.groups is based on the implicit join table and there for isn't updated until the join table is updated.

如果您尝试作为回调的一部分进行验证(before_save,after_creation等),则向对象添加错误不会触发回滚。如果回调返回false,则只会触发回滚。

If you're trying to validate as part of a callback (before_save, after_creation, etc.), then adding an error to the object won't trigger a roll back. Callbacks will only trigger a rollback if they return false. This will handle the after save implementation the question suggest.

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关系更新关系。

Another solution is to use an explicit join model. And a has_many :through relationship. The join model's table is updated in the update statement. Where as the has_many :through and HABTM relationships update the relationship after the save.

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隐式使用联接

HABTM implicitly uses a join table, so it doesn't need to be changed on the group side.

但是,您将需要修改表单以更新表单以在params哈希中提供group_id as params [:user] [:user_group_attributes] [0] [:group_id] [3]

However you will need to modify your form to update the form to supply group_id in the params hash as params[:user][:user_group_attributes][0][:group_id][3]

这篇关于在不保存的情况下验证habtm关联的长度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 20:28