繁体   English   中英

Ruby on Rails 实例与类方法

[英]Ruby on Rails instance vs class methods

我研究了 Ruby 类、实例方法之间的主要区别,我发现的主要区别是我们不需要创建该类的实例,我们可以直接在类名上直接调用该方法。

class Notifier 

def reminder_to_unconfirmed_user(user)
    headers['X-SMTPAPI'] = '{"category": "confirmation_reminder"}'
    @user = user
    mail(:to => @user["email"], :subject => "confirmation instructions reminder")
  end

end

所以,在这里我定义的实例方法reminder_to_unconfirmed_user在我的Notifier类来发送电子邮件未经证实的用户,当我运行Notifier.reminder_to_unconfirmed_user(User.last)它被调用提供了它的一个实例方法不是一个类的方法。

要定义类方法,请在方法的定义(或类的名称)中使用self关键字:

class Notifier
  def self.this_is_a_class_method
  end

  def Notifier.this_a_class_method_too
  end

  def this_is_an_instance_method
  end
end

在你的情况, reminder_to_unconfirmed_user应该被定义为一个类的方法:

class Notifier 

  def self.reminder_to_unconfirmed_user(user)
    # ...
  end

end

然后你可以像这样使用它:

Notifier.reminder_to_unconfirmed_user(User.last)

我和 OP 有同样的问题,经过仔细研究,我终于弄明白了! 其他答案只是解决了何时在 Ruby 中使用实例与类方法,但是 Rails 在幕后做了一些偷偷摸摸的事情。 问题不在于何时使用类与实例方法,而是 Rails 如何允许您像调用类方法一样调用实例方法,如上面的邮件程序示例所示。 这是由于: AbstractController::Base并且可以在这里看到: AbstractController::Base

基本上,在所有控制器(无论是您的邮件程序还是标准控制器)中,所有定义的方法都被“method_missing”拦截,然后返回该类的实例! 然后,定义的方法也被转换为公共实例方法。 因此,因为您从不实例化这些类(例如您从不执行 Mailer.new.some_method),Rails 会自动调用method_missing并返回该 Mailer 的一个实例,然后该实例利用该类中定义的所有方法。

在您的情况下,它必须是:

class Notifier 

  def self.reminder_to_unconfirmed_user(user)
    headers['X-SMTPAPI'] = '{"category": "confirmation_reminder"}'
    @user = user
    mail(:to => @user["email"], :subject => "confirmation instructions reminder")
  end

end

顾名思义:

模型上的实例方法应该用于与模型的特定实例(调用方法的实例)相关的逻辑/操作。

类方法适用于不在模型的单个实例上运行的事物,或者用于您没有可用实例的情况。 就像在某些情况下,您确实希望对几组对象应用更改。 如果您想在特定条件下更新所有用户,那么您应该使用类方法。

他们确实有不同的调用方式:

class Test
  def self.hi
    puts 'class method'
  end

  def hello
    puts 'instance method'
  end
end

Foo.hi # => "class method"
Foo.hello # => NoMethodError: undefined method ‘hello’ for Test:Class

Foo.new.hello # => instance method
Foo.new.hi # => NoMethodError: undefined method ‘hi’ for #<Test:0x1e871>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM