质量分配是提供了一种使用更少的代码,以更新模型这样
Model.create(params[:model])
@model.update_parameters(params[:model])
,而不是
@model.field1 = params[:model][:field1]
@model.field2 = params[:model][:field2]
...
@model.save
但与此功能的Rails的功能,来更新值的风险,这我们不打算。例如,如果我们只需要用户更新field1,field2和field3,并且您使用update_parameters
进行批量分配,则如果通过url或其他方式传递model[user][field4]=some_value
,则存在更新field4的风险。如果我们明确地分配代码中的字段,我们没有这种风险。但是,我们必须为每个字段设置值(无论我们正在更新还是创建),这不是非常有效。
因此,对于使用质量分配功能,我们有2个选项。首先是attr_protected
attr_protected :field4
这将保护字段4被免于质量分配从PARAMS [:模式],即使它包含字段4。为了保存field4,我们必须在 代码(@model.field4 =
)中明确调用field4的setter。但是,attr_protected
的问题在于,Rails可能会提供一些我们可能不知道的用于批量分配的其他属性。例如,如果我们定义
has_many :model2s
在Model.rb,Rails会自动提供一个方法model2_ids=
并且这可以通过质量分配访问。(如果我们在URL中给出model[model2_ids]=
,它将创建关联,根本不打算)。因此,在使用attr_protected
时,有可能会丢失像这样的属性。
因此,建议的方法是使用attr_accessible
attr_accessible :field1, :field2, :field3
这将使这些领域开放的质量分配和所有其他属性在模型中不提供质量分配。因此,推荐的方法是将我们提供的属性以用户编辑的形式提供为attr_accessible
,并且所有其他参数都将受到保护。但是,在使用此功能时,您必须确保您已将编辑所需的所有属性都包含为attr_accessible
。
对于您的情况,因为您希望用户编辑role_ids
,并且您仅为管理员用户提供了对CRUD的访问权限,所以我认为您可以使用attr_accessible :role_ids
。另一种方法是像.role_ids = params[:user][:role_ids]
那样明确地指定role_ids
。你应该使用这个,如果你有另一个你不想让用户编辑role_ids的表单。
谢谢你这个非常完整的解释。还有一个问题 - 如果我明确指定role_ids,我仍然需要使用'attr_accessible role_ids',对吧? – Kevin 2011-03-20 23:15:55
否..'attr_accessible'与显式赋值无关。即使您声明了'attr_accessible:field1'或'attr_proteected:role_ids',您也可以明确指定'@user.roles ='或'@user .role_ids ='。在你提到的问题中,他忘了将'role_ids'添加到'attr_accessible'列表中。但是,他仍然可以分配'@user.roles ='或'@user.role_ids ='。 'attr_accessible'和'attr_protected'只影响质量分配。 – rubyprince 2011-03-21 03:13:56