[英]Ruby class vs instance method confusion
Given the class: 鉴于课程:
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
and the following test code: 以及以下测试代码:
c = Contact.new
UserMailer.contact_email(c)
How is it that this code works? 这段代码是如何工作的? I thought my contact_email was an instance method, but it is being invoked as a class method, and it works.
我认为我的contact_email是一个实例方法,但它作为一个类方法被调用,并且它可以工作。
thanks for your help - as I learn Ruby and Rails :) 感谢您的帮助 - 我学习Ruby和Rails :)
-mark -标记
You're entirely correct that this looks wrong at first glance. 乍一看,这看起来是错误的,这是完全正确的。
It works because there is a method_missing
on the class ( see source ) that looks like this 它的工作原理是因为类上有一个
method_missing
( 参见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
is basically the names of the methods of your mailer that correspond to emails that can be sent, and MessageDelivery
is a little proxy class that will eventually do action_methods
基本上是邮件程序的名称,对应于可以发送的电子邮件,而MessageDelivery
是一个小代理类,最终会做
YourMailer.new.send(:contact_mailer, ...)
Off the top of my head I'm not entirely sure why this is done this way, but the basic class method to instance method proxying has been around in one form or another since the very early days of actionmailer 在我的脑海中,我不完全确定为什么这样做是这样的,但实例方法代理的基本类方法已经以某种形式存在,因为动作管理器的早期阶段
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
Sample implementation: 示例实施:
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 does something like above code. ActionMailer :: Base执行类似上面代码的操作。 Even we don't have any such method called
"fake_method"
still when the method_missing section is executed, it internally gives call to your 'sending_mail_for_you'
method. 即使我们在执行method_missing部分时仍然没有任何名为
"fake_method"
方法,它在内部调用你的'sending_mail_for_you'
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.