1

我正在使用设计进行身份验证,但还添加了一个 display_name 字段,我不希望用户在创建注册/注册后能够对其进行编辑。问题是除非我在模型中添加带有 attr_accessible 的列/字段,否则我会收到以下错误。

Can't mass-assign protected attributes: display_name

但我无法启用 attr_accessible,因为这将打开应用程序以通过编辑方法进行批量分配入侵。

我想过重写 Devise::RegistrationsController 来补充设计的 create 方法,如这个 gist所示,但是在调用 super 之前过滤参数显然会导致 display_name 根本不被保存,并且该字段将在之后的表单中显示为空验证因任何原因而失败。

是否有可以覆盖的方法或可以添加到模型中的钩子以防止在某些条件下对单个变量进行质量分配?也许我可以从参数列表 before_validation 中删除 display_name 并将其放回 after_validation,同时还使用这样的技术对其进行验证然后进行正常的无验证单一分配?当然,这仍然不会阻止通过编辑方法进行批量分配黑客攻击,所以我必须在 create 方法中向 params[:user] 哈希添加一个签名,在从 params 删除/添加 display_name 之前会检查该签名。自行验证/更新 display_name 属性。这对我来说似乎一团糟,在使用设计时是否有更好的方法来控制控制器中的质量分配?

一种快速而肮脏的方法是覆盖 Devise::RegistrationsController 就像我首先提到的那样,只需从原始设计 registrations_controller.rb 源中剪切并粘贴原始 create 方法,然后从 params[:user] 手动添加/删除 display_name在 build_resource(sign_up_params) 调用之前和之后。就在保存调用之前,如果我希望对 display_name 进行验证,我还必须将 display_name 单独添加到模型对象并使用上面提到的单个属性验证骇客。如果我将来更新设计,这种方法很有可能会破坏 create 方法,所以我已经排除了它。

在输入这些不同的方法后,我意识到我可能会覆盖 Devise::RegistrationsController 中的编辑方法,如果 params[:user][:display_name] 或任何其他不在 attr_accessible 中的属性被设置,则会引发错误。这种多处黑名单的方法也让我很不爽,在未来的扩展过程中很容易忘记将它添加到新方法中,即使黑名单在单独的私有方法中保持 DRY。不过,这似乎是最不复杂的方式。

还有其他值得尝试的方法吗?

4

2 回答 2

0

批量分配保护仅防止通过 create、save 或 assign_attributes 等方法分配参数,这些方法都将参数的哈希值作为参数。你应该仍然可以使用

user.display_name = value
user.save

在您的创建操作中。

于 2013-08-14T00:13:03.150 回答
0

如果我没有误解,您的目标只是禁止在更新用户时修改 display_name 。

您可以将 display_name 放入 attr_accessible 并在 before_update 中进行破解:

class User

  before_update :bu

  def bu
    if changed? && changed_attributes['display_name']
      self.display_name = changed_attributes['display_name']
    end
  end
end

防止修改display_name,但创建用户后无法修改display_name。

您可能需要添加一个属性作为开关并改进 before_update 以避免这种情况。

于 2013-08-14T02:58:27.713 回答