Rails: проверять только при создании или при обновлении, когда поле не пустое

17

Как я могу ограничить проверку Rails проверять только при создании OR, когда поле не пустое? Я создаю страницу настроек пользователя для приложения, над которым я работаю, и проблема заключается в том, что при обновлении с использованием параметров, предоставляемых формой, настройки сохраняются только при наличии пароля и подтверждения пароля. Я бы хотел, чтобы эти поля пароля проверялись при создании независимо от того, что, но только при обновлении, когда они предоставляются.

    
задан Jamie 18.06.2014 в 09:54
источник

4 ответа

7

Это оказалось немного проще, чем я думал. Я изменил имена ввода формы из password и password_confirmation в new_password и new_password_confirmation . Я добавил временные аксессоры для этих значений в моей модели, используя следующую строку:

attr_accessor :new_password, :new_password_confirmation

Я реализовал метод password_changed? , определенный следующим образом:

def password_changed?
    !new_password.blank?
end

Наконец, я изменил свои проверки на:

validates :new_password, presence: true, confirmation: true, length: { in: 6..20 }, on: :create
validates :new_password, presence: true, confirmation: true, length: { in: 6..20 }, on: :update, if: :password_changed?
validates :new_password_confirmation, presence: true, on: :create
validates :new_password_confirmation, presence: true, on: :update, if: :password_changed?

Я уверен, что есть лучший способ сделать это (это не очень СУХОЙ), но пока это работает. Улучшенные ответы по-прежнему будут очень оценены.

    
ответ дан Jamie 20.06.2014 в 10:11
источник
28

Если вы хотите разрешить пустые значения, используйте allow_blank с подтверждением.

class Topic < ActiveRecord::Base
  validates :title, length: { is: 5 }, allow_blank: true
end

Если вы хотите проверить только на создание, используйте на с проверками.

class Topic < ActiveRecord::Base
  validates :email, uniqueness: true, on: :create
end

Чтобы закрыть ваш случай:

class Topic
  validates :email, presence: true, if: :should_validate?

  def should_validate?
    new_record? || email.present?
  end
end
    
ответ дан cristian 18.06.2014 в 10:03
источник
5

Попробуйте

validates :<attributes>, if: Proc.new{|obj| obj.new_record? || !obj.<attribute>.blank? }

или добавьте собственные имена методов вместо имени атрибута.     

ответ дан Sanket 18.06.2014 в 10:00
источник
1

Не нужно менять имена полей, будет достаточно, чтобы заменить :password_changed? на :password_digest_changed? в вашем коде.

validates :password, presence: true, confirmation: true, length: { in: 6..20 }, on: :create
validates :password, presence: true, confirmation: true, length: { in: 6..20 }, on: :update, if: :password_digest_changed?
validates :password_confirmation, presence: true, on: :create
validates :password_confirmation, presence: true, on: :update, if: :password_digest_changed?
    
ответ дан Anton Ruban 14.02.2017 в 04:47
источник