替代HABTM的质量分配

时间:2011-03-20 16:56:05

标签: ruby-on-rails ruby-on-rails-3 has-and-belongs-to-many mass-assignment

我对此question有类似的情况,已经发布了。 Koraktor问过

  

我使用一个简单的模型进行用户授权,使用两个ActiveRecords用户和角色用户和角色彼此之间具有HABTM关系。   。   。   使用@ user.roles或@ user.role_ids手动分配角色,但不是User#new或User#update_attributes中的“魔术”。

奥列格建议

attr_accessible :role_ids

添加到用户模型中。这将允许质量分配操作员更新角色。但是,由于担心安全问题,他告诫不要使用这种方法。

我对奥列格的回应有一个跟进问题 -

在这种情况下,是否有推荐的方法在不使用批量分配的情况下更新角色?

另外,假设

  1. 您对用户进行身份验证,
  2. 只允许管理员通过在users_controller中放置before_filter来使用CRUD用户,
  3. 是对role_ids进行大规模分配还是一个有效的问题吗?

1 个答案:

答案 0 :(得分:2)

批量分配是Rails的一项功能,可以使用更少的代码来更新像这样的模型

Model.create(params[:model])
@model.update_parameters(params[:model])

而不是

@model.field1 = params[:model][:field1]
@model.field2 = params[:model][:field2]
...
@model.save

但是有了这个功能,就会有更新我们不想要的值的风险。例如,如果我们只想让用户更新field1,field2和field3并使用update_parameters进行质量分配,那么如果从网址传递model[user][field4]=some_value,则存在更新field4的风险或通过任何其他方式。如果我们明确指定代码中的字段,我们就没有这种风险。但是,我们必须为每个字段设置值(无论我们在哪里更新或创建),这都不是很有效率。

因此,对于使用质量分配功能,我们有2个选项。首先是attr_protected

attr_protected :field4

这将保护field4免于从params [:model]中进行质量分配,即使它包含field4。为了保存field4,我们必须明确地调用field4的setter 代码(@model.field4 =)。但是,attr_protected的问题是Rails可能提供一些我们可能不知道的大规模分配的其他属性。例如,如果我们定义

has_many :model2s

在Model.rb中,Rails将自动提供方法model2_ids=,这可以通过批量分配来访问。(如果我们在U​​RL中给出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 .role_ids = params[:user][:role_ids]。如果您有其他不希望用户编辑role_ids的表单,则应使用此方法。