[英]Instance Methods vs. Class methods For a Helper Class - Ruby, 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.