为什么 Rails 实例方法可以用作 rspec 中的 class 方法
Why Rails instance method can be used as class method in rspec
我在一篇关于在 Rails 应用程序中发送邮件的文章中找到了一个片段:
class ExampleMailerPreview < ActionMailer::Preview
def sample_mail_preview
ExampleMailer.sample_email(User.first)
end
end
在此 link 中:http://www.gotealeaf.com/blog/handling-emails-in-rails。
我不知道为什么方法:sample_email()
,在我看来应该是一个实例方法,在这里可以像class方法一样被访问为ExampleMailer.sample_email()
。谁能解释一下?
这不是 rspec 的事,而是 ActionMailer 的事。正在查看:
https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb
看看第135-146行的注释:
# = Sending mail
#
# Once a mailer action and template are defined, you can deliver your message or defer its creation and
# delivery for later:
#
# NotifierMailer.welcome(User.first).deliver_now # sends the email
# mail = NotifierMailer.welcome(User.first) # => an ActionMailer::MessageDelivery object
# mail.deliver_now # generates and sends the email now
#
# The <tt>ActionMailer::MessageDelivery</tt> class is a wrapper around a delegate that will call
# your method to generate the mail. If you want direct access to delegator, or <tt>Mail::Message</tt>,
# you can call the <tt>message</tt> method on the <tt>ActionMailer::MessageDelivery</tt> object.
该功能是通过在 ActionMailer::Base class 上定义一个 method_missing 方法来实现的,如下所示:
def method_missing(method_name, *args) # :nodoc:
if action_methods.include?(method_name.to_s)
MessageDelivery.new(self, method_name, *args)
else
super
end
end
本质上,在 ActionMailer 实例(评论示例中的 NotifierMailer)上定义一个方法,然后在 class 上调用它会创建一个新的 MessageDelivery 实例,该实例委托给 ActionMailer 的新实例 class.
我在一篇关于在 Rails 应用程序中发送邮件的文章中找到了一个片段:
class ExampleMailerPreview < ActionMailer::Preview
def sample_mail_preview
ExampleMailer.sample_email(User.first)
end
end
在此 link 中:http://www.gotealeaf.com/blog/handling-emails-in-rails。
我不知道为什么方法:sample_email()
,在我看来应该是一个实例方法,在这里可以像class方法一样被访问为ExampleMailer.sample_email()
。谁能解释一下?
这不是 rspec 的事,而是 ActionMailer 的事。正在查看:
https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb
看看第135-146行的注释:
# = Sending mail
#
# Once a mailer action and template are defined, you can deliver your message or defer its creation and
# delivery for later:
#
# NotifierMailer.welcome(User.first).deliver_now # sends the email
# mail = NotifierMailer.welcome(User.first) # => an ActionMailer::MessageDelivery object
# mail.deliver_now # generates and sends the email now
#
# The <tt>ActionMailer::MessageDelivery</tt> class is a wrapper around a delegate that will call
# your method to generate the mail. If you want direct access to delegator, or <tt>Mail::Message</tt>,
# you can call the <tt>message</tt> method on the <tt>ActionMailer::MessageDelivery</tt> object.
该功能是通过在 ActionMailer::Base class 上定义一个 method_missing 方法来实现的,如下所示:
def method_missing(method_name, *args) # :nodoc:
if action_methods.include?(method_name.to_s)
MessageDelivery.new(self, method_name, *args)
else
super
end
end
本质上,在 ActionMailer 实例(评论示例中的 NotifierMailer)上定义一个方法,然后在 class 上调用它会创建一个新的 MessageDelivery 实例,该实例委托给 ActionMailer 的新实例 class.