Railstutorial.org 第8章:摘要方法定义

Railstutorial.org Chapter 8: digest method definition

我目前正在学习 Michael Hartl 的 Rails 教程,我发现了一个我不太明白的方法定义:

class User < ActiveRecord::Base


before_save { self.email = email.downcase }
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

  # Returns the hash digest of the given string.
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end
end

关键部分是User.digest的定义...为什么他写def User.digest(string)而不仅仅是def digest(string)...

我们在用户 class 中,因此 User.<method_name> 应该可以访问其中的每个方法。那么这样定义一个方法是不是多余或者是错误的?

以下是class方法,它们是等价的:

def User.digest(string)
  # MY LOGIC
end

def self.digest(string)
  # MY LOGIC
end

Class 方法直接在 class 上调用,例如 User.digest("my_string")

We are in the User class so every method in it should be accessible by User.

不幸的是,这是真的。使用 User.<method_name>.

只会调用 class 方法

如果你定义了一个方法

def digest(string)
  # MY LOGIC
end

以上是一个 实例方法 ,将在 User class 的实例(对象)上调用(不是直接在 class ) 如:

user = User.new
user.digest("string")

如果你这样做def digest(string),你实际上是在定义一个实例方法。

在此处阅读有关 class 和实例方法的更多信息:http://www.railstips.org/blog/archives/2009/05/11/class-and-instance-methods-in-ruby/

Michael Hartl 实际上在底部解释了为什么他以这种方式定义 class 方法(第 8.6 节第 1 点)。

...we defined the new token and digest class methods by explicitly prefixing them with User. This works fine and, because they are actually called using User.new_token and User.digest, it is probably the clearest way to define them....

定义用户 class 方法的其他替代方法是:

def self.digest(string)
  #your code here
end

class << self
  def digest(string)
    #your code here
  end
end

希望对您有所帮助!我也通过他的书学习了 Rails :)