关于rails中的关键字“self”,让我们以下面的代码片段为例。 我知道关键字指的是类本身的实例,例如表达式“self.encrypted_password”。 无论如何,我很少知道为什么右侧的参数作为参数传递的属性也没有以self关键字作为前缀?
任何人都可以告诉我何时使用或不使用我的示例后面的self关键字?
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
before_save :encrypt_password
private
def encrypt_password
self.encrypted_password = encrypt(password)
end
def encrypt(string)
string # Only a temporary implementation!
end
end
答案 0 :(得分:8)
答案很简单:范围可见性。
def encrypt_password
self.encrypted_password = encrypt(password)
end
(或者更确切地说,应该在运行时)某些称为password
。在您的情况下,它是数据库中的属性。但它也可以是局部变量。如果找不到此名称,将引发错误。
但是 以encrypted_password
为前缀self
明确声明您要更新实例属性。否则,将创建新的局部变量encrypted_password
。显然,不是你想要的效果。
这里有一小段代码
class Foo
attr_accessor :var
def bar1
var = 4
puts var
puts self.var
end
end
f = Foo.new
f.var = 3
f.bar1
输出
4
3
因此,正如我们所看到的,var
的分配没有self
关键字,因此,现在范围内有两个名称var
:局部变量和实例属性。 Instance属性由局部变量隐藏,因此如果您确实想要访问它,请使用self
。
答案 1 :(得分:2)
这个问题与Rails无关,但与Ruby有关。当你查看代码时:
def encrypt_password
self.encrypted_password = encrypt(password)
end
它将由Ruby翻译成:
self.encrypted_password =
是对encrypted_password=
方法的方法调用。 encrypt(password)
包含2个方法调用。
password
通过声明password
调用方法attr_accessor :password
,该方法是模型的真实属性。该声明创建了两种方法:
password
:属性的吸气器password=
:属性的设置者请参阅@Sergio_Tulentsev的解释,如何通过局部变量隐藏getter(在您的实现中不是这种情况,没有局部变量)。
encrypt
的返回值调用方法password
。因此,使用self.
可以明确表示您(一直)进行方法调用,而不是直接访问该属性。如果你想这样做,你必须在实例方法中使用@password = <some value>
,但我更喜欢带有self.password = <some value>
的样式。
我希望现在很清楚你的代码是如何被解释的。
答案 2 :(得分:0)
setter method =&gt;使用自我
当您需要写时,请使用self
换句话说,当您需要分配值时。
getter method =&gt;不要使用自我
without self
当您需要阅读时。{
当您需要读取值时。
例如:
def write_name(name)
self.name = name
end
def read_name
name
end
在您的情况下,虚拟属性password
不以self
关键字为前缀,因为它仅 读取(getter)。
encrypted_password
将存储在数据库中,它在db(setter)中写。因此使用self
。
修改强>:
Michael HARTL对同一案件有相同的解释:
(当然,正如我们已经注意到的,在分配属性时self不是可选的,因此在这种情况下我们必须编写self.encrypted_password。)
http://ruby.railstutorial.org/chapters/modeling-and-viewing-users-two#sec:an_active_record_callback
(7.1.3的最后一行)