如何在rails中使用self关键字
关于rails中的关键字“self”,让我们以下面的代码片段为例。 我知道关键字是指类本身的实例,例如表达式“self.encrypted_password”。 无论如何,我很少知道为什么作为右侧参数传递的属性“password”也没有以self关键字作为前缀?
任何人都可以启发我什么时候使用或不使用我的例子后的self关键字给?
class User 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
回答
答案很简单:范围可见性。
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
。
这个问题与Rails无关,但与Ruby有关。 当你看你的代码时:
def encrypt_password self.encrypted_password = encrypt(password) end
它将由Ruby翻译成:
-
self.encrypted_password =
是对encrypted_password=
方法的方法调用。 - 此方法由Rails动态生成,因为存在具有相同名称的数据库列。
-
encrypt(password)
包含2个方法调用。-
password
通过声明attr_accessor :password
调用方法password
,该password
是模型的真实属性。 该声明创建了两种方法:-
password
:属性的getter -
password=
:属性的setter
-
请参阅@Sergio_Tulentsev的解释,如何通过局部变量隐藏getter(在您的实现中不是这种情况,没有局部变量)。
- 用方法调用
password
的返回值调用方法encrypt
。
-
所以使用self.
明确表示您(始终)有方法调用,不直接访问该属性。 如果你想这样做,你必须在实例方法中使用@password =
,但我更喜欢self.password =
的样式。
我希望现在很清楚你的代码是如何被解释的。
setter method =>使用self
当你需要写东西时使用self
。
换句话说,当您需要分配值时。
getter方法=>不要使用self
当你需要阅读某些东西时, 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的最后一行)