我正在尝试了解何时使用self.method_name与何时使用Classname.method_name。
在下面的示例中,为什么“before_create”需要引用“User.hash_password”而不是“self.hash_password”或只是“hash_password”?
由于我们已经在User类中,我认为before_create方法会“知道”“hash_password”是其自己的类的成员,并且不需要任何特殊语法来引用它。
require 'digest/sha1'
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :password
validates_presence_of :name, :password
validates_uniqueness_of :name
def before_create
self.hashed_password = User.hash_password(self.password)
end
def after_create
@password = nil
end
def self.login(name, password)
hashed_password = hash_password(password || "")
self.find(:first, :conditions => ["name = ? and hashed_password = ?", name, hashed_password])
end
def try_to_login
User.login(self.name, self.password)
end
private
def self.hash_password(password)
Digest::SHA1.hexdigest(password)
end
end
答案 0 :(得分:13)
def before_create
self.hashed_password = User.hash_password(self.password)
end
在此示例中,User.hash_password
调用类 hash_password
上的User
方法,而self.hashed_password=
调用hashed_password=
方法 User
的此特定实例。
如果将User.hash_password
替换为self.hash_password
,Ruby会抱怨NoMethodError
,因为类hash_password
中不存在User
名称的实例方法}。不过,您可以将其替换为self.class.hash_password
。
如果用self.hashed_password=
替换hashed_password=
,Ruby将创建一个名为hashed_password
的局部变量,而不是调用实例方法hashed_password=
。如果要调用属性编写器,则需要显式添加self
。
方法定义中的self
(def self.hash_password
)使hash_password
成为类方法而不是实例方法。在此上下文中,self
指的是类。在实例方法的上下文中,self
引用实例。
答案 1 :(得分:12)
您正在询问类方法和实例方法之间的区别。
有几种方法可以定义类方法:
class Klass
def Klass.method_name
..
end
end
与做:
相同class Klass
def self.method_name
..
end
end
或首选的红宝石成语:
class Klass
class << self
def method_name
..
end
end
end
如果已宣布Klass,你也可以这样做..
def Klass.method_name
..
end
或:
class << Klass
def method_name
..
end
end
或者您甚至可以使用Module #extend:
Klass.extend(Module.new { def method_name; puts 'ducky'; end })
就像你会向对象添加单例方法一样。实际上,类方法是在类级别上运行的单例方法。
在rails ActiveRecord中,你有一个类方法'find'可以在任何Model上使用:
Person.find(1)
和'save'等实例方法对单个对象进行操作
person = Person.find(1)
...
person.save
在我正在处理的当前项目中,我有一个包含数据源的模型Feed。我需要定期运行一个更新所有Feed的方法,这样我就有了一个fetch_all方法来完成这个。
class Feed < ActiveRecord::Base
// class method Feed.fetch_all
def self.fetch_all
Feed.all.each do |feed|
feed.fetch_value
end
end
// instance method
def fetch_value
// grabs updated value and saves
end
end
答案 2 :(得分:1)
我还没有深入研究Ruby,但是根据你的描述,我会说hash_password是一个静态方法,或者能够以静态方式使用。