Rails —自我与@

| 我正在遵循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
我发布了一个先前的问题,关于
before_save
行不通,事实证明,我不小心做的事情是将我的crypto_password写为:
def encrypt_password
    @encrypted_password = encrypt(password)
end
我知道,如果self.encrypted_pa​​ssword设置了encryption_password属性,但是@encrypted_pa​​ssword为什么也不能这样做呢?在对上一个有关“ 1”不起作用的帖子的答复中,有人说实例变量在方法以我原来的编码方式结束后被“忘记了”,为什么会这样呢?有人可以在上面的代码中解释self和@的不同之处吗? 注意:我已经看过这里和这里的帖子,但是他们都说\“ self \”正在调用
attribute =
方法,而且我什至不知道该方法在这里可能存在的原因,因为我从未创建过它,或者声明带有“ 5”的加密密码。因此,我仍然感到困惑,这不是重新发布这些问题。     
已邀请:
        Rails已自动为您添加了
encrypted_password
的访问器,因为the7ѭ表中存在一个具有该名称的字段。 您添加到表格中的任何字段都将通过
self.field_name
自动变为可用。 这是Michael Hartl \的教程在
users
表中创建
encrypted_password
字段的地方。 还要查看链接页面中的
user_spec.rb
(清单7.3),作者正在测试其中是否存在
encrypted_password
字段。 更新: 正如@mu所指出的,
@
用于Ruby实例变量(aka \“ iv \”)。但是ѭ6是Rails定义的“属性”,不是实例变量。 如果运行
User.find(1).instance_variables
,您将看到存在一个名为
@attributes
的iv,其类型为
Hash
。 在那个iv内部是ѭ6的存储位置。 Rails为“ 6”定义了访问器方法,该方法获取/设置该方法的数据。 属性在
@attributes
Hash
中。 请注意,您还可以通过
User
类中调用的
@attributes[\"encrypted_password\"]
获取/设置数据(但是访问器方法是实现此目的的便捷方法)。     
如果您愿意,我想改一下答案。 我在这篇文章中解释过,一旦您创建了一个与数据库的多个表名之一相同名称的(rails-)模型,rails的“ magic \”将创建setter和getter。为了修改您的表的记录。 这是因为您的模型继承了ActiveRecord :: Base类的所有方法,该类定义了基本的CRUD访问器(创建,读取,更新,删除)。 与您的问题相关的关键点是,您不知道Rails如何实现与数据库表列相关的实例变量,并且您不应该。 :)您只需要知道,此时,您就可以使用CRUD(创建,读取,更新,删除)数据库列\“ encrypted_pa​​ssword \”的setter和getter。 在您的示例中,rails使用名为@encrypted_pa​​ssword的实例变量,rails使用称为@attributes [\“ encrypted_pa​​ssword \”]]的哈希实例变量,或者rails使用名为@you_will_never_guess_encrypted_pa​​ssword的实例变量。 -- 这是您不了解实例变量的内部rails行为的一个好地方。在2019年,Rails的进一步开发可能会导致该框架使用@ complicated-hash-instance-variable来存储cryptod_password值。 实际上,最好的方法是让Rails使用实例变量管理其“私有”,“事务”;),并仅使用它提供给您的getter和setter方法。 因此,您的应用程序将在下个世纪仍然可以使用cryptomated_pa​​ssword(我希望是^^)。 因此,如果您使用@encrypted_pa​​ssword,则它可能适用于某些“虚构”版本的导轨,而不再适用于其他导轨版本。实际上,使用当前版本的rails不能正常工作。 -- 第二个关键点是,当您要使用为您的crypto_password数据库表列创建的getter \“ encrypted_pa​​ssword \” Rails时,请在其前面加上\“ self \”以便告诉Ruby:\“确定,我想使用我的User实例变量的encryption_password方法。\“ 在Ruby中,通过将名称传递给接收方来调用方法。 你这样写:
my_receiver.my_method
在您的情况下,我们将方法cryptorated_pa​​ssword传递给User实例变量。但是我们不知道该实例变量的命名方式,因此我们使用self来告诉Ruby:“我在谈论User类的任何实例变量,该实例变量都调用了cryptod_password方法”。 例如,我们可以将实例变量命名为\“ toto \”:
toto = User.new
因此ѭ26将显示加密的密码,在这种情况下,我们的代码中的self将引用toto。 但是,多亏了Ruby,如果您在调用方法时不给任何接收者,Ruby会假定您将其传递给self。 参考:实用程序员指南 因此,在您的示例中,您甚至无需将\“ self。\”作为前缀。 你可以这样写:
class User < ActiveRecord::Base

    def encrypt_password
        encrypted_password = encrypt(password)
    end
end
我希望这有助于阐明这个有趣的主题。     
        TL; DR- 如果要将widget_count保存回数据库,请始终写write28。 (但是,请务必阅读详尽的答案,作为了解其宝贵之处的原因。)     

要回复问题请先登录注册