简体   繁体   English

Ruby on Rails 实例与类方法

[英]Ruby on Rails instance vs class methods

I have studied major difference between Ruby class ,instance method and the major difference I found is we don't need to create instance of that class we can directly call that method on class name directly.我研究了 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

So,here I defined instance method reminder_to_unconfirmed_user in my Notifier class to send email to unconfirmed users, and when I run Notifier.reminder_to_unconfirmed_user(User.last) it get called provided it's a instance method not a class method.所以,在这里我定义的实例方法reminder_to_unconfirmed_user在我的Notifier类来发送电子邮件未经证实的用户,当我运行Notifier.reminder_to_unconfirmed_user(User.last)它被调用提供了它的一个实例方法不是一个类的方法。

To define a class method, use the self keyword in the method's definition (or the class' name):要定义类方法,请在方法的定义(或类的名称)中使用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

In your case, reminder_to_unconfirmed_user should be defined as a class method:在你的情况, reminder_to_unconfirmed_user应该被定义为一个类的方法:

class Notifier 

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

end

Then you can use it like this:然后你可以像这样使用它:

Notifier.reminder_to_unconfirmed_user(User.last)

I had the same question the OP did and after digging around I finally figured it out!我和 OP 有同样的问题,经过仔细研究,我终于弄明白了! The other answers just addressed when to use instance vs class methods in Ruby however Rails does some sneaky stuff behind the scences.其他答案只是解决了何时在 Ruby 中使用实例与类方法,但是 Rails 在幕后做了一些偷偷摸摸的事情。 The question wasn't when to use class vs instance methods but instead how come Rails allows you to call an instance method as if it's a class method as shown by his mailer example above.问题不在于何时使用类与实例方法,而是 Rails 如何允许您像调用类方法一样调用实例方法,如上面的邮件程序示例所示。 It's due to: AbstractController::Base and can be seen here: AbstractController::Base这是由于: AbstractController::Base并且可以在这里看到: AbstractController::Base

Basically, in all controllers (whether they be your mailer or a standard controller), all defined methods are intercepted by "method_missing" and then returns an instance of that class!基本上,在所有控制器(无论是您的邮件程序还是标准控制器)中,所有定义的方法都被“method_missing”拦截,然后返回该类的实例! The defined methods are then also converted to public instance methods.然后,定义的方法也被转换为公共实例方法。 Thus, because you never instantiate these classes (for example you never do Mailer.new.some_method) Rails automagically calls method_missing and returns an instance of that Mailer which then takes advantage of all the methods defined within that class.因此,因为您从不实例化这些类(例如您从不执行 Mailer.new.some_method),Rails 会自动调用method_missing并返回该 Mailer 的一个实例,然后该实例利用该类中定义的所有方法。

In your case it must be :在您的情况下,它必须是:

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

As their name suggests:顾名思义:

Instance methods on a model should be used for logic/operations that relate to a specific instance of a model (the one on which the method is called.)模型上的实例方法应该用于与模型的特定实例(调用方法的实例)相关的逻辑/操作。

Class methods are for things which don't operate on an individual instance of a model or for cases where you don't have the instance available to you.类方法适用于不在模型的单个实例上运行的事物,或者用于您没有可用实例的情况。 Like in some cases you do want to apply changes on few group of objects.就像在某些情况下,您确实希望对几组对象应用更改。 If you want to update all users on a specific condition, Then you should go for class method.如果您想在特定条件下更新所有用户,那么您应该使用类方法。

They do have different way of calling :他们确实有不同的调用方式:

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