From 95e06e6682b3bc7f813336142213697eac36e401 Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Thu, 7 Apr 2016 13:16:54 -0700 Subject: Disallow calling `#deliver_later` after local message modifications. They would be lost when the delivery job is enqueued, otherwise. Prevents a common, hard-to-find bug like: ```ruby message = Notifier.welcome(user, foo) message.message_id = my_generated_message_id message.deliver_later ``` The message_id is silently lost here! *Only the mailer arguments are passed to the delivery job.* This raises an exception now. Make modifications to the message within the mailer method or use a custom Active Job to manage delivery instead of using #deliver_later. --- actionmailer/lib/action_mailer/message_delivery.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'actionmailer/lib') diff --git a/actionmailer/lib/action_mailer/message_delivery.rb b/actionmailer/lib/action_mailer/message_delivery.rb index 5fcb5a0c88..d638057d72 100644 --- a/actionmailer/lib/action_mailer/message_delivery.rb +++ b/actionmailer/lib/action_mailer/message_delivery.rb @@ -18,6 +18,7 @@ module ActionMailer @mailer = mailer @mail_method = mail_method @args = args + @obj = nil end def __getobj__ #:nodoc: @@ -91,8 +92,19 @@ module ActionMailer private def enqueue_delivery(delivery_method, options={}) - args = @mailer.name, @mail_method.to_s, delivery_method.to_s, *@args - ActionMailer::DeliveryJob.set(options).perform_later(*args) + if @obj + raise "You've accessed the message before asking to deliver it " \ + "later, so you may have made local changes that would be " \ + "silently lost if we enqueued a job to deliver it. Why? Only " \ + "the mailer method *arguments* are passed with the delivery job! " \ + "Do not access the message in any way if you mean to deliver it " \ + "later. Workarounds: 1. don't touch the message before calling " \ + "#deliver_later, 2. only touch the message *within your mailer " \ + "method*, or 3. use a custom Active Job instead of #deliver_later." + else + args = @mailer.name, @mail_method.to_s, delivery_method.to_s, *@args + ActionMailer::DeliveryJob.set(options).perform_later(*args) + end end end end -- cgit v1.2.3