Reputation: 33
Given the class:
class UserMailer < ActionMailer::Base
default from: "[email protected]"
def contact_email(contact)
@contact = contact
mail(to: '[email protected]', 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.
thanks for your help - as I learn Ruby and Rails :)
-mark
Upvotes: 3
Views: 148
Reputation: 4251
Check 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
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.
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.
Upvotes: 0
Reputation: 84114
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
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
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
Upvotes: 5