仅当密码为params时才验证has_secure_password的存在

时间:2013-10-20 13:55:01

标签: ruby-on-rails ruby-on-rails-3 validation passwords ruby-on-rails-4

我有4个与用户模型关联的表单,这就是我希望他们表现的方式 -

  1. 注册(新) - 需要密码 - email, name, password, password_confirmation
  2. 修改设置(编辑) - 密码不需要 - email, name
  3. 更改密码 - 需要密码,登录用户的页面才能更改密码 - current_password, password, password_confirmation
  4. 重设密码 - 需要密码,未经身份验证的用户更改密码的页面,从密码重置电子邮件到达后password, password_confirmation
  5. 我最接近的验证解决方案是 -

    validates :password, presence: true, length: { minimum: 6 }, on: :update, if: lambda{ |u| u.password.blank? }

    这将满足第1,3和4点,但它不允许用户更新属性,即def update(第2点),因为没有params[:user][:password],因此{presence: true}验证触发了。

    当表单包含密码字段时,validate_presence_of :password的最佳方法是什么?

4 个答案:

答案 0 :(得分:4)

试试这个:

validates :password, presence: true, length: { minimum: 6 }, allow_nil: true

当且仅当密码字段出现在表单上时,它才会验证密码。

但是这很危险,如果有人从html中删除密码字段,那么这个验证不会触发,因为那样你就不会得到密码的索引。所以你应该这样做:

validates :password, presence: true, length: { minimum: 6 }, if: ->(record) { record.new_record? || record.password.present? || record.password_confirmation.present?  }

答案 1 :(得分:1)

要回答您的问题,最好是change_passwordreset_password控制器操作并在那里进行验证。

首先,让您的模型仅在创建时或在已经输入时验证密码:

validates :password, :presence => true,
                     :length => { minimum: 6 },
                     :if => lambda{ new_record? || !password.nil? }

然后,对于您的新控制器操作,有以下几点:

class UsersController < ApplicationController

  def change_password
    ...
    if params[:user][:password].present?
      @user.update_attributes(params[:user])
      redirect_to root_path, notice: "Success!"
    else
      flash.now.alert "Please enter password!"
      render "change_password"
    end
  end
end

为reset_password做同样的事情,你应该是金色的!

答案 2 :(得分:0)

你可以这样做:

validates: validator_method


def validator_method(params_input)
if params.empty?
...
else
your_logic_her
end

您必须原谅我使用伪代码,但您的想法是创建一个单独的方法来验证而不是使用验证:

答案 3 :(得分:0)

你可以使用devise gem或者看看它的实现。这是源代码 https://github.com/plataformatec/devise