鉴于课程:
class UserMailer < ActionMailer::Base
default from: "do-not-reply@mark.com"
def contact_email(contact)
@contact = contact
mail(to: 'm@mark.com', from: @contact.email, subject: "Website Contact")
end
end
以及以下测试代码:
c = Contact.new
UserMailer.contact_email(c)
这段代码是如何工作的?我认为我的contact_email是一个实例方法,但它作为一个类方法被调用,并且它可以工作。
感谢您的帮助 - 我学习Ruby和Rails:)
-mark
答案 0 :(得分:5)
乍一看,这看起来是错误的,这是完全正确的。
它有效,因为有一个method_missing
在类(see source)上看起来像这样
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
action_methods
基本上是邮件的方法名称,对应于可以发送的电子邮件,MessageDelivery
是一个最终会做的小代理类
YourMailer.new.send(:contact_mailer, ...)
脱离我的头脑我不完全确定为什么这样做是这样的,但实例方法代理的基本类方法已经以某种形式存在,因为动作管理器的早期版本
答案 1 :(得分:0)
检查source
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
示例实施:
class MyMailer
def self.method_missing(method, *args)
puts "Here, I can call any instance method"
end
def sending_mail_for_you
puts "I am actually sending mail for you"
end
end
#notice, fake_method is not defined in the MyMailer class.
MyMailer.fake_method
This will give output:
=> "Here, I can call any instance method"
"I am actually sending mail for you"
ActionMailer :: Base执行类似上面代码的操作。
即使我们在执行method_missing部分时仍然没有任何名为"fake_method"
的方法,它在内部会调用您的'sending_mail_for_you'
方法。