Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby class vs instance method confusion

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

like image 464
Mark Feinholz Avatar asked Apr 24 '26 20:04

Mark Feinholz


1 Answers

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

like image 126
Frederick Cheung Avatar answered Apr 27 '26 09:04

Frederick Cheung



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!