2011-10-23 12 views
6

ho ottenuto il seguente modello User:Rails convalida che password_confirmation è presente quando la password è anche presente o è stato cambiato

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 

Questi convalide non del tutto fare quello che speravo che sarebbe. E 'possibile effettuare le seguenti operazioni:

# 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 

Quindi quello che voglio è la seguente:

  • password richiesta sul creare, deve essere di 6 caratteri a lungo
  • password_confirmation richiesto sul creare, deve corrispondere la password
  • utente non dovrebbe avere a presentare password quando l'aggiornamento login_name
  • password non può essere eliminato aggiornata

Qualcosa che mi confonde è che le rotaie getta un errore di metodo se uso password_changed? al contrario di :password_digest_changed? nel mio convalida password_confirmation. Non capisco perché.

Quindi qualcuno sa cosa sto facendo male qui?

risposta

13

password non è una colonna nel database, giusto? Solo un attributo?

Quindi non esiste il metodo password_changed?, che sarebbe disponibile se password fosse una colonna. Piuttosto, dovresti semplicemente controllare se password è impostato.

Qualcosa di simile:

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

Anche se questo risolve il problema iniziale si stavano avendo, ancora sarà non del tutto fare quello che vuoi, come è solo controllando la presenza, ed è necessario che sia presente e corrispondenza password. Qualcosa come il seguente dovrebbe funzionare (in combinazione con la convalida di cui sopra).

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 

Se non hai mai visto :confirmation prima, è una convalida standard che cerca foo e foo_confirmation e fa in modo che siano la stessa cosa.

Si noti che è comunque necessario verificare la presenza di password_confirmation

+0

Ahh, hai ragione, la password e password_confirmation non sono campi db in modo che spiega perché non ho accesso a metodi sporchi per loro. L'utente è ancora in grado di eliminare la propria password durante l'aggiornamento e può abbreviare anche a meno di 6 caratteri. Qual è il mio problema principale qui – stephenmurdoch

+0

L'ho modificato per risolvere altri problemi. Sembra che dovrebbe funzionare. – numbers1311407

+3

Grazie il tuo codice era molto vicino a quello che ho finito per usare. Alla fine sono stato in grado di rimuovere la convalida ': presence' perché' secure_password' verifica già la presenza di ': password_digest'. Ho fatto un [gist] (https://gist.github.com/1308130) per ricordarmi in futuro – stephenmurdoch

Problemi correlati