0

Я на самом деле создаю программное обеспечение для массовой рассылки бюллетеней, из которого я могу создать новый список макетирования на лету, загрузить шаблон, а затем отправить электронное письмо подписчикам из этого списка, сделав что-то вроде этого:Metaprogramming in ActionMailer :: Base

@suscribers.each do |suscriber| 
    NewsletterMailer.delay.send("#{@list.name}_newsletter", suscriber, @newsletter) 
end 

(Обратите внимание, что метод задержки, потому что я использую sidekiq для моих фоновых заданий)

Я попытался переопределить method_missing от ActionMailer :: Base внутри класса NewsletterMailer, чтобы справиться с этой логикой, но просто не выполняется. Я просто получаю сообщение NoMethodError, говорящее «неопределенный метод` testing_newsletter »для NewsletterMailer: Class».

Я искал исходный код ActionMailer :: Base # method_missing, и я вижу, что он уже выполняет некоторую логику, чтобы мы могли делать Mailer.name_of_the_email.deliver без вызова new. Кроме того, этот метод защищен.

Но есть ли способ, по которому я все еще могу отправить электронное письмо из метода, который не является жестко закодированным внутри моего класса NewsletterMailer? Есть ли способ динамически добавлять методы в контроллер ActionMailer?

Большое спасибо.

ответ

1

Если вы определили его как def method_missing ..., вы создали метод экземпляра, но ваш код означает, что вы отправляете сообщение для динамического самого класса. Вы должны определить self.method_missing по адресу NewsletterMailer, если вы хотите, чтобы он выполнялся, как вы его написали.

Это, как говорится, я бы рекомендовал против этого дизайна для вашего конкретного случая. Идея, которую я хотел бы иметь в виду, заключается в том, что у вас есть поведение - методы и действия, которые имеют все информационные бюллетени, - и данные, в которых описываются сведения о любом данном списке и/или его информационном бюллетене. В большинстве случаев они должны оставаться отдельными и разными, с кодом, описывающим поведение, и базой данных, содержащей ваши данные. Не имеет смысла определять новый метод для каждого списка рассылки, когда у вас может быть только метод send_newsletter, который принимает список в качестве аргумента.

+0

Большое спасибо. Сначала я рассказывал об одном и том же дизайне, но, хотя он слишком сильно нарушал действие ActionMailer, потому что, даже если это почти одинаковое поведение, шаблон не тот, и философия ActionMailer :: Base была загрузите шаблон на основе имени метода. Из-за этого я, хотя каждый информационный бюллетень нуждался в собственном методе. Но я узнал, что могу указать имя_таблицы внутри метода почты. Зная это, я буду реорганизовывать все и использовать один метод для отправки всех информационных бюллетеней. –

0

Вы можете использовать class_eval определить новые методы на лету:

class SomeClass 
end 

[:foo, :bar].each do |name| 
    SomeClass.class_eval <<COMMAND 
    def self.#{name} 
     puts "Hello from #{name}" 
    end 
COMMAND 
end 

SomeClass.foo 
SomeClass.bar 
Смежные вопросы