Как отключить проверку пароля/подтверждения при использовании has_secure_password в Rails 3.2?

У меня есть пользовательская модель, настроенная как таковая:

class User < ActiveRecord::Base
  has_secure_password

  # callbacks -------------------------------------------------------------------------
  before_create { generate_token(:auth_token) }

  # setup accessible (or protected) attributes for your model and validation ----------
  attr_accessible :email, :password, :password_confirmation

  # validations
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email    , presence: true,
                        uniqueness: { case_sensitive: false },
                        format: { with: VALID_EMAIL_REGEX }

  validates :password             , length: { minimum: 6 } 

  validates :password_confirmation, presence: true

Но я не хочу, чтобы проверка пароля и/или пароля_подтверждения выполнялась при обновлении пользователя, если только пользователь не пытается изменить свой пароль.

Таким образом, если пользователь обновляет свою информацию в форме без указания пароля и/или подтверждения, все должно пройти успешно. Если пользователь обновляет свою информацию и включает пароль и/или подтверждение, проверки должны выполняться.

Каков наилучший способ добиться этого?


person wgpubs    schedule 18.03.2012    source источник
comment
Вы также можете обновить атрибуты, используя @user.update_attributes({}) или @user.update_attribute :attr_name, значение.   -  person nverinaud    schedule 07.06.2012


Ответы (2)


Вы можете добавить условное :if к обоим валидаторам:

Опция 1:

validates :password             , length: { minimum: 6 }, :if => :validate_password?
validates :password_confirmation, presence: true        , :if => :validate_password?

def validate_password?
  password.present? || password_confirmation.present?
end

Вариант 2:

Или используйте метод для проверки, переместив проверки проверки в метод, а не в виде отдельных вызовов validates:

validate :check_password, :on => :update

def check_password
  return unless password.present? || password_confirmation.present?
  ..validations for both attributes here.. 
  ..check presence, length etc. as required and add to the errors variable as necessary..
end
person Zabba    schedule 18.03.2012
comment
Вариант 1 хорош, как раз то, что мне нужно. Но password_validation должен быть password_confirmation. - person dougnorton; 09.10.2012
comment
!пароль.ноль? лучше, чем .present?, в противном случае возможна регистрация без пароля - person Hoetmaaiers; 12.09.2013
comment
.present? возвращает true, если строка имеет вид nil? или blank?, поэтому она гарантирует, что строка содержит один или несколько символов, кроме пробелов. - person Zabba; 12.09.2013

В дополнение к ответу Заббы, вариант 1 также можно записать так:

with_options if: :password_provided? do
    validates :password, :password_confirmation, presence: true, length: { minimum: 12 }
end

def password_provided?
    password.present? || password_confirmation.present?
end
person thde    schedule 17.04.2018