Ruby on Rails实例方法和类方法

3
我研究了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

所以,在我的Notifier类中,我定义了一个实例方法reminder_to_unconfirmed_user来向未确认的用户发送电子邮件,当我运行Notifier.reminder_to_unconfirmed_user(User.last)时,它会被调用,前提是它是一个实例方法而不是类方法。


1
那问题是什么? - Meier
他的问题是为什么一个实例方法可以像类方法一样在类上调用。下面发布了一个答案。 - bkunzi01
3个回答

6

要定义一个类方法,可以在方法的定义中使用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)

2
我和提问者有同样的问题,在研究了一番之后,我终于找到了答案!其他回答只是讲解了在Ruby中何时使用实例方法和类方法,然而Rails在幕后做了一些诡异的事情。问题不在于何时使用类方法和实例方法,而是为什么Rails允许你调用一个实例方法,就像它是一个类方法一样,就像上面的mailer示例所示。这是由于AbstractController :: Base引起的,并且可以在此处查看:AbstractController::Base 基本上,在所有控制器中(无论是您的邮件程序还是标准控制器),所有定义的方法都会被“method_missing”拦截,然后返回该类的实例!然后,这些定义的方法也会转换为公共实例方法。因此,因为您从未实例化这些类(例如,您从未执行Mailer.new.some_method),Rails自动调用method_missing并返回该Mailer的实例,然后利用该类中定义的所有方法。

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


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>

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