Rails User 模型类里为什么要加一个 password 的虚拟属性

tiseheaini · March 20, 2012 · Last by azhao replied at March 23, 2012 · 3299 hits

User 模型类里为什么要加一个 password 的虚拟属性 在 railscasts-china.com 上看太檑老师 @poshboytl 的视频,在看第二章 user-authentication 时弄不明白一个问题,太檑老师在 User 模型类里写了一个 password 的虚拟属性,开始我在模仿老师的代码时总是出错,后来注意到这一点后给代码加上一个 password 的虚拟属性后,问题莫名其妙的没了,我记得我的代码中从没调用过 password 这个方法,问题出在哪里呢??

忘了打代码了,代码在这里

class User < ActiveRecord::Base
    validates :login, :presence => true
    def password
        @password      
    end

    def password=(pass)
        return unless pass
        @password = pass
        generate_password(pass)
    end

    private
    def generate_password
        salt = Array.new(10){rand(1024).to_s(36)}.join
        self.salt, self.hashed_password = salt, Digest::SHA256.hexdigest(pass+salt)
    end

end


大家没听明白吗

因为你的 form 里会用到 f.password_field :password,但是你的 table 里实际是没有 password 这个字段的

-.-!!! 其实你可以叫我同学的.... 或者 Terry.... 哈哈哈哈~~ :D

之所以称之为虚拟属性,就是说这个属性在你数据库中并不存在。我们希望通过重定义他的赋值方法 (set 方法) 来间接的给 hashed_password 赋值...

分享一个 attr_accessor 的技巧 http://ruby-china.org/topics/413

@poshboytl 太雷。这名字太给力了。。

#5 楼 @bony 其实有个木字旁的... :D 不过从读音上很容易被认为很雷.... -.-!

有点思路了,可是还不是那么明白,我的 form 里会用到 f.password_field :password 但不清楚哪个校验方法用到了 password 字段(当然我的数据库里没有 password 字段),谁能再仔细的讲一讲

def password
    @password       
end

def password(pass)
    return unless pass
    @password = pass
    generate_password(pass)
end

def 两次 password,是为什么?

#8 楼 @fredwu 你不说我都还没注意....他敲错了吧

原本的代码应该是

def password=(pass)
    return unless pass
    @password = pass
    generate_password(pass)
  end


我敲错了,我改过来,有人能解释一下这个虚拟属性吗?是不是,假如我的 User 模型类中用到 address,可我的数据库里写的是 user_address 字段,那么我就要写一个 set_address 的方法呢??

#9 楼 @poshboytl 能不能再解释一下这个虚拟属性?是不是,假如我的 User 模型类中用到 address,可我的数据库里写的是 user_address 字段,那么我就要写一个 set_address 的方法呢??

model 中的属性一般都是与数据库表一致的,一般情况下也会与表单传过来的属性一致,

当表单属性与数据库属性不一致,就需要设置一个属性做映射,比如你的例子中把 password 转换成 hashed_password,实现一个转换规则

你的@password就是一个虚拟属性,get 和 set 方法是这个属性的表单与数据库的映射规则,这里就是把表单里的 password 字段加密

You need to Sign in before reply, if you don't have an account, please Sign up first.