如何在rails中使用self关键字

时间:2012-01-13 01:15:22

标签: ruby-on-rails ruby oop

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

3 个答案:

答案 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=方法的方法调用。
  • 此方法由Rails动态生成,因为存在一个具有相同名称的数据库列。
  • encrypt(password)包含2个方法调用。

    1. password通过声明password调用方法attr_accessor :password,该方法是模型的真实属性。该声明创建了两种方法:
      • password:属性的吸气器
      • password=:属性的设置者
    2. 请参阅@Sergio_Tulentsev的解释,如何通过局部变量隐藏getter(在您的实现中不是这种情况,没有局部变量)。

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

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

(7.1.3的最后一行)