3

我有 4 个与 User 模型关联的表单,这就是我希望它们的行为方式 -

  1. 注册(新) - 需要密码 -email, name, password, password_confirmation
  2. 编辑设置(编辑) - 不需要密码 -email, name
  3. 更改密码- 需要密码,登录用户更改密码的页面 -current_password, password, password_confirmation
  4. 重置密码- 需要密码,未经身份验证的用户在收到密码重置电子邮件后更改密码的页面 -password, password_confirmation

我拥有的最接近的验证解决方案是 -

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

4 回答 4

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?  }
于 2013-10-20T15:05:07.763 回答
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 做同样的事情,你应该是金子!

于 2013-10-20T14:49:42.350 回答
0

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

于 2013-10-20T14:53:30.350 回答
0

你可以这样做:

validates: validator_method


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

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

于 2013-10-20T14:12:32.723 回答