设计更新密码

时间:2013-08-28 20:39:41

标签: ruby-on-rails ruby devise password-recovery

我想更改编辑密码进程。在编辑密码页面上,我有一个字段:foo,我想检查用户是否正确输入了它。

我创建了PasswordsController并覆盖了更新方法,我在其中添加了用于测试的代码:foo与数据库中的相同:

def update
    self.resource = resource_class.reset_password_by_token(resource_params)

    # this is code that I added
    unless self.resource.foo == params[resource_name][:foo]
      self.resource.errors.add(:foo, "Foo not correct")
    end

    if resource.errors.empty?
      resource.unlock_access! if unlockable?(resource)
      flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
      set_flash_message(:notice, flash_message) if is_navigational_format?
      sign_in(resource_name, resource)
      respond_with resource, :location => after_resetting_password_path_for(resource)
    else
      binding.pry
      respond_with resource
    end
  end

假设我输入" test" in:foo field,但在数据库中,它的值是" fake"。它将在视图上打印错误(" Foo不正确")但它将填充:foo字段,其中包含来自数据库的值(" fake")而不是我输入的值(" test& #34;。)

我应该重新定义reset_password_by_token或使用我的自定义方法,但想知道是否有更优雅的方法来解决这个问题?

2 个答案:

答案 0 :(得分:1)

尝试使用before_action(可能是before_filter,具体取决于您的Rails版本):

class PasswordsController < ...

  before_action :check_foo, :only => :update

  ...

  private

    def check_foo
      # get resource
      # check foo
      # redirect if foo is not valid
    end

end

您也可以将其更改为仅扩展现有RegistrationsController。只需重新使用update的现有Devise实现,而无需重新实现它,只需在前面添加过滤器。

要阻止更新对象上的:foo,请先过滤params哈希,删除:foo字段,然后再将其传递给reset_password_by_token

def remove_foo(hash)
    hash.delete_if { |k, v| k == :foo }
end

...

self.resource = resource_class.reset_password_by_token(remove_foo(resource_params))

或者,如果您使用Rails 4, or Strong Parameters,请不要允许。

答案 1 :(得分:0)

为表单上的字段使用不同的名称(假设为'bar')然后您将测试更改为:

...
unless self.resource.foo == params[resource_name][:bar]
    self.resource.errors.add(:foo, "Foo not correct")
end
...

注意:在视图中,您将无法使用表单构建器的东西,因为如果'bar'不是模型对象的属性,它会阻塞,但您可以使用html直接向表单添加任何标记或像FormTagHelper::text_field_tag这样的rails辅助方法。