Как можно вызывать методы класса в почтовых программах, если они не определены как таковые?
При отправке почты в Rails обычно делается что-то вроде этого:
UserMailer.password_reset(user).deliver
Но если мы заглянем внутрь UserMailer
, то увидим следующее:
def password_reset(user) # not self.password_reset
# ...
end
Обратите внимание, что имя метода не имеет префикса self
. Глядя на него, кажется, что вам нужно сначала создать экземпляр объекта, как показано ниже. Как Rails это делает?
UserMailer.new.password_reset(user).deliver
2 ответа:
Это отличный вопрос. В источнике (https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb ), Rails использует method_missing для создания нового экземпляра ActionMailer. Вот соответствующая выдержка из источника:
def method_missing(method_name, *args) # :nodoc: if respond_to?(method_name) new(method_name, *args).message else super end end
Обратите внимание, что метод
self.deliver
является устаревшим, посмотрите на приведенный ниже код. Поскольку методdeliver
определен как метод класса, вам не нужно создавать экземпляр класса mailer.Action_mailer / deprecated_api.rb
module ActionMailer module DeprecatedApi #:nodoc: extend ActiveSupport::Concern module ClassMethods # Deliver the given mail object directly. This can be used to deliver # a preconstructed mail object, like: # # email = MyMailer.create_some_mail(parameters) # email.set_some_obscure_header "frobnicate" # MyMailer.deliver(email) def deliver(mail, show_warning=true) if show_warning ActiveSupport::Deprecation.warn "#{self}.deliver is deprecated, call " << "deliver in the mailer instance instead", caller[0,2] end raise "no mail object available for delivery!" unless mail wrap_delivery_behavior(mail) mail.deliver mail end
Отправка почты
Как только действие и шаблон почтовой программы определены, вы можете доставить свое сообщение или создать его и сохранить для последующей доставки:
mail = Notifier.welcome(david) # => a Mail::Message object mail.deliver # sends the email #Above 2 steps can be combined Notifier.welcome(david).deliver
Вы никогда не создаете свой экземпляр. класс Мейлера. Скорее, вы просто вызываете метод, который вы определили для самого класса.
Метод
password_reset
возвращает объект Mail::Message, который затем можно просто сказать deliver , чтобы отправить себя.