如何在rails中使用self关键字

关于rails中的关键字“self”,让我们以下面的代码片段为例。 我知道关键字是指类本身的实例,例如表达式“self.encrypted_pa​​ssword”。 无论如何,我很少知道为什么作为右侧参数传递的属性“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个方法调用。

    1. password通过声明attr_accessor :password调用方法password ,该password是模型的真实属性。 该声明创建了两种方法:
      • password :属性的getter
      • password= :属性的setter

    请参阅@Sergio_Tulentsev的解释,如何通过局部变量隐藏getter(在您的实现中不是这种情况,没有局部变量)。

    1. 用方法调用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_pa​​ssword。)

http://ruby.railstutorial.org/chapters/modeling-and-viewing-users-two#sec:an_active_record_callback

(7.1.3的最后一行)