diff --git a/actionmailer/lib/action_mailer/message_delivery.rb b/actionmailer/lib/action_mailer/message_delivery.rb index 9fe88a795c..0986364b0d 100644 --- a/actionmailer/lib/action_mailer/message_delivery.rb +++ b/actionmailer/lib/action_mailer/message_delivery.rb @@ -142,14 +142,37 @@ module ActionMailer else job = @mailer_class.delivery_job - if job <= MailDeliveryJob + if use_new_args?(job) job.set(options).perform_later( @mailer_class.name, @action.to_s, delivery_method.to_s, args: @args) + elsif job <= DeliveryJob + job.set(options).perform_later( + @mailer_class.name, @action.to_s, delivery_method.to_s, *@args) else + ActiveSupport::Deprecation.warn(<<~EOM) + In Rails 6.2, Action Mailer will pass the mail arguments inside the `:args` keyword argument. + The `perform` method of the #{job} needs to change and forward the mail arguments + from the `args` keyword argument. + + The `perform` method should now look like: + + `def perform(mailer, mail_method, delivery, args:)` + EOM + job.set(options).perform_later( @mailer_class.name, @action.to_s, delivery_method.to_s, *@args) end end end + + def use_new_args?(job) + parameters = job.public_instance_method(:perform).parameters + + parameters.find do |key, name| + return true if key == :keyreq && name == :args + + key == :keyrest + end + end end end diff --git a/actionmailer/test/legacy_delivery_job_test.rb b/actionmailer/test/legacy_delivery_job_test.rb index a9b2a160d4..92b2645e3a 100644 --- a/actionmailer/test/legacy_delivery_job_test.rb +++ b/actionmailer/test/legacy_delivery_job_test.rb @@ -11,6 +11,21 @@ class LegacyDeliveryJobTest < ActiveSupport::TestCase class LegacyDeliveryJob < ActionMailer::DeliveryJob end + class LegacyArgumentDeliveryJob < ActiveJob::Base + def perform(mailer, mail_method, delivery_method, *args) + end + end + + class NewArgumentDeliveryJob < ActiveJob::Base + def perform(mailer, mail_method, delivery_method, args:) + end + end + + class KeyRestArgumentJob < ActiveJob::Base + def perform(mailer, mail_method, delivery_method, **kwargs) + end + end + setup do @previous_logger = ActiveJob::Base.logger ActiveJob::Base.logger = Logger.new(nil) @@ -68,6 +83,36 @@ class LegacyDeliveryJobTest < ActiveSupport::TestCase end end + test "triggers a deprecation warning when a delivery job use legacy arguments" do + with_delivery_job(LegacyArgumentDeliveryJob) do + assert_deprecated("Action Mailer will pass the mail arguments inside the `:args` keyword argument") do + perform_enqueued_jobs do + DelayedMailer.test_message(1, 2, 3).deliver_later + end + end + end + end + + test "does not trigger a deprecation warning when a delivery job use a required `args` kwargs" do + with_delivery_job(NewArgumentDeliveryJob) do + assert_not_deprecated do + perform_enqueued_jobs do + DelayedMailer.test_message(1, 2, 3).deliver_later + end + end + end + end + + test "does not trigger a deprecation warning when a delivery job use a keyrest argument" do + with_delivery_job(KeyRestArgumentJob) do + assert_not_deprecated do + perform_enqueued_jobs do + DelayedMailer.test_message(1, 2, 3).deliver_later + end + end + end + end + private def with_delivery_job(job) old_params_delivery_job = ParamsMailer.delivery_job