2

我想更改编辑密码过程。在编辑密码页面上,我有一个字段: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

假设我在 :foo 字段中输入“test”,但在数据库中它的值是“fake”。它将在视图上打印错误(“Foo 不正确”),但它会使用来自数据库的值(“fake”)而不是我输入的值(“test”)填充 :foo 字段。

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

4

2 回答 2

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. 只需重新使用现有的 Devise 实现update而不重新实现它,只需在前面添加过滤器即可。

为防止更新: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 或 Strong Parameters,请不要这样做。

于 2013-08-28T20:51:57.280 回答
0

为表单上的字段使用不同的名称(比如说“bar”),然后您将测试更改为:

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

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

于 2013-08-28T20:55:55.390 回答