0

我实际上正在创建一个时事通讯群发软件,我可以从中即时创建一个新的邮件列表,上传一个模板,然后从该列表中向订阅者发送一封电子邮件,执行如下操作:

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

(请注意,延迟方法是因为我在后台作业中使用了sidekiq)

我试图覆盖 NewsletterMailer 类中 ActionMailer::Base 的 method_missing 来处理这个逻辑,但它似乎没有被执行。我刚刚收到一个 NoMethodError,说“NewsletterMailer:Class 的未定义方法 `testing_newsletter'”。

我查看了 ActionMailer::Base#method_missing 源代码,发现它已经在执行一些逻辑,因此我们可以在不调用 new 的情况下执行 Mailer.name_of_the_email.deliver。此外,此方法受到保护。

但是,有没有办法我仍然可以从我的 NewsletterMailer 类中未硬编码的方法发送电子邮件?有没有办法将方法动态添加到 ActionMailer 控制器?

非常感谢。

4

2 回答 2

1

如果您将其定义为 def method_missing ...,则您创建了一个实例方法,但您的代码表明您正在将动态消息发送到类本身。如果您希望它在您编写时执行,self.method_missing您需要定义。NewsletterMailer

话虽如此,对于您的特定情况,我建议您不要使用这种设计。我要记住的想法是你有行为——所有时事通讯共有的方法和动作——和数据,它描述了任何给定列表和/或其时事通讯的细节。在大多数情况下,这些应该保持独立和不同,您的代码描述行为,数据库保存您的数据。为每个邮件列表定义一个新方法几乎没有意义,因为您可以只拥有一个send_newsletter将列表作为参数的方法。

于 2013-08-06T18:14:44.333 回答
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 
于 2013-08-06T18:14:24.520 回答