没有质量分配的设计中的自定义字段

时间:2013-08-14 00:07:29

标签: ruby-on-rails ruby validation devise mass-assignment

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

Can't mass-assign protected attributes: display_name

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

我考虑重写Devise :: RegistrationsController以补充设计的创建方法,如this gist所示,但在调用super之前过滤params显然会导致display_name根本没有被保存,并且字段会显示在验证因任何原因失败后,在表单中为空。

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

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

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

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

2 个答案:

答案 0 :(得分:0)

质量分配保护仅通过诸如create,save或assign_attributes之类的方法来防止分配参数,这些方法都将参数哈希作为参数。您仍然可以使用

user.display_name = value
user.save

在您的创建操作中。

答案 1 :(得分: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以避免出现这种情况。