2010-05-04 91 views
0

这段代码来自于使用rails书的敏捷web开发..我不明白代码的这部分内容... 用户是一个名称为hashed_pa​​ssword,盐为字段的模型。但是在代码中他们提到了密码和密码确认,而模型中没有这样的字段。模型只有hashed_pa​​ssword。我相信错误与我同在。请为我清除:) 用户模型有名称,hashed_pa​​ssword,salt。所有字段都是字符串使用rails的敏捷web开发

require 'digest/sha1' 
class User < ActiveRecord::Base 
     validates_presence_of :name 
     validates_uniqueness_of :name 
     attr_accessor :password_confirmation 
     validates_confirmation_of :password 
     validate :password_non_blank 

     def self.authenticate(name, password) 
      user = self.find_by_name(name) 
      if user 
      expected_password = encrypted_password(password, user.salt)    
      if user.hashed_password != expected_password 
       user = nil 
      end 
      end 
      user 
     end 

     def password 
      @password 
     end 

     def password=(pwd) 
      @password = pwd 
      return if pwd.blank? 
      create_new_salt 
      self.hashed_password = User.encrypted_password(self.password, self.salt) 
     end 

     private 
     def password_non_blank 
      errors.add(:password,"Missing password")if hashed_password.blank? 
     end 

     def create_new_salt 
      self.salt = self.object_id.to_s + rand.to_s 
     end 

     def self.encrypted_password(password, salt) 
      string_to_hash = password + "wibble" + salt 
      Digest::SHA1.hexdigest(string_to_hash) 
     end 
end 

回答

4

attr_accessor用于为实例变量创建getter/setter方法。例如:

attr_accessor :foo 

# is equivalent to 

def foo 
    @foo 
end 

def foo=(value) 
    @foo = value 
end 

在代码你粘贴,def passworddef password=手动定义。不过,我有点被利用的困惑:

attr_accessor :password_confirmation 

validates_confirmation_of :foo会自动创建一个foo_confirmation访问,所以这应该是:

attr_accessor :password 
validates_confirmation_of :password 

添加一个简单的before_save回调加密的密码和你全部完成了。

require 'digest/sha1' 
class User < ActiveRecord::Base 

    # attrs 
    attr_accessor :password 

    # class methods 
    class << self 
    def encrypt(password, salt) 
     Digest::SHA1.hexdigest("--#{salt}--#{password}--"); 
    end 
    end 

    # validation 
    validates_presence_of  :name 
    validates_confirmation_of :password 

    # callbacks 
    before_save :encrypt_password 

    protected 

    def encrypt_password 
    return if password.blank? 
    if new_record? 
     self.salt = Digest::SHA1.hexdigest("--#{Time.now}--#{name}--") 
    end 
    self.encrypted_password = User.encrypt(password, salt) 
    end 

end 
3

由于您不希望以明文形式将密码存储在数据库中,因此您将创建一个名为password的虚拟属性。当你写你这样做:

def password=(pwd) 
    @password = pwd 
    return if pwd.blank? 
    create_new_salt 
    self.hashed_password = User.encrypted_password(self.password, self.salt) 
end 

这样一来,当你调用密码=“维布勒”它实际上是加密“维布勒”,并在数据库中存储加密的值来代替。

attr_accessor :password_confirmation 

即一条线是相同的,如果你:

+1

谢谢...这部分代码 attr_accessor:password_confirmation validates_confirmation_of:password – felix 2010-05-04 18:13:50

0

在该示例中,password_confirmation属性使用attr_accessor中辅助,其设置为你的吸气剂和mutator在一行代码添加到模型中这样写的:

def password_confirmation 
    @password_confirmation 
end 

def password_confirmation=(pwd_conf) 
    @password_confirmation = pwd_conf 
end 

密码的存取在模型中明确定义:

 def password 
      @password 
     end 

     def password=(pwd) 
      @password = pwd 
      return if pwd.blank? 
      create_new_salt 
      self.hashed_password = User.encrypted_password(self.password, self.salt) 
     end 

这些虚拟属性是在模型代码中定义的,因为它们不存在于数据库表中,模型从其中获取属性的其余部分,因为您不希望它们存储在数据库中。