2011-10-23 13 views
6

Mam następujący model użytkownika:Szyny potwierdzające, że password_confirmation jest obecny, gdy hasło jest także obecny lub została zmieniona

class User < ActiveRecord::Base 
    # Users table has the necessary password_digest field 
    has_secure_password 
    attr_accessible :login_name, :password, :password_confirmation 

    validates :login_name, :presence=>true, :uniqueness=>true 

    # I run this validation on :create so that user 
    # can edit login_name without having to enter password  
    validates :password,:presence=>true,:length=>{:minimum=>6},:on=>:create 

    # this should only run if the password has changed 
    validates :password_confirmation, 
      :presence=>true, :if => :password_digest_changed? 
end 

Te walidacje nie dość robienia tego, co miałem nadzieję, że będzie. Jest to możliwe, aby wykonać następujące czynności:

# rails console 
u = User.new :login_name=>"stephen" 
u.valid? 
# => false 
u.errors 
# => :password_digest=>["can't be blank"], 
# => :password=>["can't be blank", "please enter at least 6 characters"]} 

# so far so good, let's give it a password and a valid confirmation 
u.password="password" 
u.password_confirmation="password" 

# at this point the record is valid and does save 
u.save 
# => true 

# but we can now submit a blank password from console 
u.password="" 
# => true 
u.password_confirmation="" 
# => true 

u.save 
# => true 
# oh noes 

Więc czego chcę jest następująca:

  • hasło wymagane tworzyć, musi być 6 znaków w długim
  • password_confirmation wymaganego na tworzenie, musi pasować hasło
  • użytkownik nie powinien podawać hasła podczas aktualizacji nazwy logowania
  • hasło nie może być usunięte przy aktualizacji

Coś, co jest mylące mnie to, że szyny rzuca żadna metoda błąd, jeśli używam password_changed? w przeciwieństwie do :password_digest_changed? w moim walidacji password_confirmation. Nie rozumiem, dlaczego.

Czy ktoś wie, co tu robię źle?

Odpowiedz

13

password nie jest kolumną w bazie danych, prawda? Tylko atrybut?

Więc nie ma metody password_changed?, która byłaby dostępna, gdyby password była kolumną. Zamiast tego powinieneś po prostu sprawdzić, czy w ogóle ustawiono password.

Coś jak:

validates :password_confirmation, :presence => true, :if => '!password.nil?' 

Mimo że rozwiązuje początkowe problemy miałaś, to nadal nie całkiem to, co chcesz, jak to sprawdzanie tylko obecność, i trzeba go będzie obecny i dopasowanie hasła. Powinno działać coś takiego jak poniższe (w połączeniu z powyższym sprawdzaniem poprawności).

validates :password, 
      # you only need presence on create 
      :presence => { :on => :create }, 
      # allow_nil for length (presence will handle it on create) 
      :length => { :minimum => 6, :allow_nil => true }, 
      # and use confirmation to ensure they always match 
      :confirmation => true 

Jeśli nigdy wcześniej nie widział :confirmation wcześniej, jest to standardowy walidacji, który wygląda na foo i foo_confirmation i upewnia się, że są takie same.

Należy pamiętać, że trzeba jeszcze sprawdzić pod kątem obecności password_confirmation

+0

Ahh, masz rację, hasło i password_confirmation nie są polami db tak to wyjaśnia, dlaczego nie mam dostępu do brudnych metod nich. Użytkownik wciąż może usunąć swoje hasło podczas aktualizacji i może je skrócić do mniej niż 6 znaków. Który jest moim głównym problemem tutaj – stephenmurdoch

+0

Edytowałem to, by zająć się twoimi innymi problemami. Wygląda na to, że to powinno działać. – numbers1311407

+3

Dzięki temu kod był bardzo zbliżony do tego, z czego skorzystałem. W końcu udało mi się usunąć walidację ': presence', ponieważ' secure_password' już sprawdza obecność ': password_digest'. Zrobiłem [sedno] (https://gist.github.com/1308130), aby przypomnieć sobie w przyszłości – stephenmurdoch

Powiązane problemy