Ruby on Rails中的self有什么作用?

6

我正在Railcasts上练习Rails,遇到了一些需要理解的内容。

我不明白authenticate方法中的"self"是什么意思。于是我删除了它,并测试了我的应用程序的登录功能,结果出现了错误:

error:

**NoMethodError in SessionsController#create
undefined method `authenticate' for #<Class:0x00000102cb9000**>

我希望有人能够解释一下 "Self" 到底是做什么的。我一直试图弄清楚到底发生了什么,但是却无法理解。
该方法在模型中定义,并在sessions_controller中调用.. 我一直在不断地删除我的应用程序并从头开始学习它,每次重新开始时,许多事情对我来说都很有意义,但是我被卡在了“self”上。
我只是那种喜欢了解为什么某些东西工作的人。
控制器:
 def create
    user = User.authenticate(params[:email], params[:password])
    if user
      session[:user_id] = user.id
      redirect_to root_path, :notice => "Logged In"
    else
      flash.now.alert = "Invalid credentials"
      render "new"
    end
  end

模型:

 def self.authenticate(email, password)
      user = find_by_email(email)
    if user && user.password_hash ==  BCrypt::Engine.hash_secret(password, user.password_salt)
      user
    else
      nil
    end
  end
4个回答

13

这是一个基础的 Ruby 问题。在这种情况下,self 用于定义类方法。

    class MyClass
      def instance_method
        puts "instance method"
      end

      def self.class_method
        puts "class method"
      end
    end

它们像这样使用:

    instance = MyClass.new
    instance.instance_method

或者:

    MyClass.class_method
希望这能解决一些问题。另外,请参考:http://railstips.org/blog/archives/2009/05/11/class-and-instance-methods-in-ruby/

1
稍微扩展一下你的回答:def object.my_foo_method。在obj上定义了my_foo_method方法。在你的回答中,selfClass类的对象(即MyClass类)。因此,它定义了该类的方法。 - Swanand
在实例中不应该使用 @ 符号吗,例如 @instance = ...? - Michael Durrant
考虑到这是Rails,很可能会在视图中使用。 - Michael Durrant

5

self 定义了一个的方法,而不是类的实例。因此,使用 def self.authenticate,您可以执行以下操作:

u = User.authenticate('email@domain.com','p@ss')

Instead of doing…

u = User.new
u.authenticate('email@domain.com','p@ss')

那样的话,您就不必创建用户实例来验证用户身份。

除了避免需要实例化一个类以使用方法之外,是否还有其他原因要定义类方法而不是实例方法? - LazerSharks

3

为了完整性和避免将来的麻烦,我还想指出这两个是等效的:

class User
  def self.authenticate
  end
end

class User
  def User.authenticate
  end
end

喜好问题。

2
class User
    def self.xxx 
    end
end

这是一种定义类方法的方式,同时

class User    
    def xxx 
    end
end

将定义一个实例方法。

如果从def中删除self.,当您执行以下操作时,将会出现找不到方法的错误:

User.authenticate

因为您试图在类上调用方法而不是类的实例。要使用实例方法,您需要一个类的实例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接