Frage

I am actually creating a newsletter massmailling software from which I can create a new mailling list on the fly, upload a template, and then send an email to the suscribers from that list doing something like this:

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

(Note that the delay method is because I use sidekiq for my background jobs)

I have tried to override the method_missing from ActionMailer::Base inside the NewsletterMailer class to handle this logic, but it just doesn't seem to be executed. I just receive a NoMethodError saying "undefined method `testing_newsletter' for NewsletterMailer:Class".

I looked up the ActionMailer::Base#method_missing source code and I see that it is already executing some logic so we can be able to do Mailer.name_of_the_email.deliver without calling new. Also, this method is protected.

But, is there a way I can still send an email from a method that is not hardcoded inside my NewsletterMailer class? Is there a way to add methods dynamically to an ActionMailer controller?

Thanks a lot.

War es hilfreich?

Lösung

If you've defined it as def method_missing ..., you have created an instance method, but your code indicates you are sending the dynamic message to the class itself. You need to define self.method_missing on NewsletterMailer if you want it to execute as you've written it.

That being said, I would recommend against this design for your particular case. The idea I would keep in mind is that you have behavior - the methods and actions that all newsletters have in common - and data, which describes the particulars of any given list and/or its newsletter. In most cases, these should remain separate and distinct, with your code describing behavior, and a database holding your data. It makes little sense to define a new method for each mailing list, when you could just have a method send_newsletter that takes the list as an argument.

Andere Tipps

You can use class_eval to define new methods on the fly:

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 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top