Rails - 自我与@

Kva*_*ass 17 ruby instance-variables self ruby-on-rails-3

我正在关注Michael Hartl的RoR教程,它涵盖了密码加密的基础知识.这是目前的用户模型:

class User < ActiveRecord::Base
    attr_accessor :password

    attr_accessible :name, :email,: password, :password_confirmation

    email_regex = /^[A-Za-z0-9._+-]+@[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+[A-Za-z]$/
                                              #tests for valid email addresses.

    validates :name, :presence => true,
                     :length => {:maximum => 50}
    validates :email, :presence => true,
                      :format => {:with => email_regex},
                      :uniqueness => {:case_sensitive => false}
    validates :password, :presence => true,
                         :length => {:maximum => 20, :minimum => 6},
                         :confirmation => true

    before_save :encrypt_password

    private

    def encrypt_password
        self.encrypted_password = encrypt(password)
    end

    def encrypt(string)
        string
    end
end
Run Code Online (Sandbox Code Playgroud)

我发布了一个关于before_save不工作的上一个问题,事实证明我不小心做的是将我的encrypt_password写成:

def encrypt_password
    @encrypted_password = encrypt(password)
end
Run Code Online (Sandbox Code Playgroud)

我知道如果self.encrypted_pa​​ssword设置encrypted_pa​​ssword属性,但为什么@encrypted_pa​​ssword也没有这样做呢?在上一篇关于before_save不工作的帖子的回复中,有人说实例变量在方法以我最初编码的方式结束后被"遗忘" - 为什么会这样?有人可以解释一下self和@ 在上面代码的上下文中的工作方式有何不同

注意:我已经看过这里这里的帖子,但是他们都说"self"正在调用attribute =方法,我甚至不知道这个方法在这里是如何存在的,因为我从来没有创建过它或者声明了encrypted_pa​​ssword w/attr_accessor.所以我仍然感到困惑,这不是重新发布这些问题.

Zab*_*bba 20

encrypted_passwordRails为您自动添加了访问者,因为users表中存在该名称的字段.

您添加到表格中的任何字段都将自动通过self.field_name.

这是Michael Hartl的教程encrypted_passwordusers表格中创建字段的地方.

另请查看user_spec.rb链接页面中的(清单7.3),作者正在测试该encrypted_password字段的存在.

更新:

正如@mu指出的那样,@它用于Ruby实例变量(又名"iv").但它encrypted_password是由Rails定义的"属性",并不是实例变量.

如果你运行User.find(1).instance_variables,你会看到有一个叫做iv @attributes的类型Hash.

在那里iv encrypted_password是存储的地方.Rails定义了访问器方法encrypted_password,用于获取/设置该属性的数据@attributes Hash.

请注意,您也可以通过@attributes["encrypted_password"]User类中调用来获取/设置数据(但是访问器方法是方便的方法).

  • @Kvass:`@`不起作用,因为ActiveRecord没有注意你的实例变量,方法调用有效,因为AR补充说这是一种改变`encrypted_pa​​ssword`属性的方法.AR的属性与对象的实例变量分开. (2认同)