Ruby class instance class 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 does this code work? I thought my contact_email was an instance method, but it is called as a class method and it works.

thanks for your help - as I am learning Ruby and Rails :)

-Mark

+3


source to share


2 answers


You are absolutely right that at first glance it looks wrong.

This works because there is method_missing

a 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 method names of your mailer that correspond to the emails sent, and MessageDelivery

is a little proxy class that will eventually do

YourMailer.new.send(:contact_mailer, ...)

      

At the top of my head, I'm not entirely sure why it is done this way, but the base class method for the proxy instance method has been in one form or another since the very early days of actionmailer

+5


source


Check

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

      

Implementation example:



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 the code above. Even we do not have such a method, which is called "fake_method"

even when the method_missing section is executed, it internally calls your method 'sending_mail_for_you'

.

0


source







All Articles