2011-10-23 28 views
6

我有以下的用戶模型:Rails的驗證該password_confirmation存在時,密碼也存在改變或已改變

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 

這些驗證不太做什麼,我希望他們會。這是可能做到以下幾點:

# 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 

所以,我想是這樣的:上創建必需的,必須在創建所需的長

  • password_confirmation 6個字符

    • 密碼,必須匹配密碼
    • 更新登錄名時用戶不必提交密碼
    • 更新時無法刪除密碼

    東西是困惑我是,如果我用password_changed?在我password_confirmation驗證反對:password_digest_changed?該軌道拋出一個沒有方法錯誤。我不明白爲什麼。

    所以有人知道我在這裏做錯了嗎?

  • 回答

    13

    password不是數據庫中的一列,對不對?只是一個屬性?

    因此沒有password_changed?方法,如果password是一列,則該方法可用。相反,你應該檢查看是否設置了password

    喜歡的東西:

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

    雖然能夠解決您遇到的首要問題,它仍然沒有完全做你想做的,因爲它只是檢查存在,並且你需要它存在匹配密碼。類似下面的內容應該可以工作(結合上面的驗證)。

    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 
    

    如果你以前從未見過:confirmation,這是一個標準的驗證,以查找foofoo_confirmation,並確保它們是相同的。

    請注意,您仍然需要檢查password_confirmation

    +0

    稀釋的情況下,你說得對,密碼和password_confirmation不是數據庫字段,這樣解釋了爲什麼我沒有獲得骯髒的方法他們。用戶仍然可以在更新時刪除他們的密碼,並且可以將其縮短到少於6個字符。這是我的主要問題 – stephenmurdoch

    +0

    我編輯它來解決您的其他問題。看起來它應該工作。 – numbers1311407

    +3

    謝謝你的代碼非常接近我最終使用的。最後,我能夠刪除':presence'驗證,因爲'secure_password'已經檢查是否存在':password_digest'。我做了一個[gist](https://gist.github.com/1308130)來提醒自己 – stephenmurdoch