From 3860e6b2bf486d8b27d433daab358dbc68ae3448 Mon Sep 17 00:00:00 2001
From: Johannes Opper <johannes.opper@gmail.com>
Date: Tue, 7 Jul 2015 21:52:28 +0200
Subject: Fixes #20799

When `#perform_later` is called the locale isn't stored on the
queue, which results in a locale reset when the job is performed.

An example of the problem:

    I18n.locale = 'de'
    HelloJob.perform_now # german message, correct

but

    I18n.locale = 'de'
    HelloJob.perform_later # english message, incorrect

This PR attaches the current I18n.locale to every job during the
serialization process. It is then restored during deserialization
and used to perform the job with the correct locale.

It falls back to the default locale if no serialized locale is
found in order to provide backward compatibility with previously
stored jobs. It is not necessary to clear the queue for the update.
---
 activejob/test/cases/job_serialization_test.rb       | 16 ++++++++++++++++
 activejob/test/cases/translation_test.rb             | 20 ++++++++++++++++++++
 activejob/test/integration/queuing_test.rb           | 17 +++++++++++++++++
 activejob/test/jobs/translated_hello_job.rb          | 10 ++++++++++
 .../test/support/integration/dummy_app_template.rb   |  6 +++++-
 .../test/support/integration/test_case_helpers.rb    |  4 ++++
 6 files changed, 72 insertions(+), 1 deletion(-)
 create mode 100644 activejob/test/cases/translation_test.rb
 create mode 100644 activejob/test/jobs/translated_hello_job.rb

(limited to 'activejob/test')

diff --git a/activejob/test/cases/job_serialization_test.rb b/activejob/test/cases/job_serialization_test.rb
index db22783030..e23380a7bf 100644
--- a/activejob/test/cases/job_serialization_test.rb
+++ b/activejob/test/cases/job_serialization_test.rb
@@ -12,4 +12,20 @@ class JobSerializationTest < ActiveSupport::TestCase
     GidJob.perform_later @person
     assert_equal "Person with ID: 5", JobBuffer.last_value
   end
+
+  test 'serialize includes current locale' do
+    assert_equal :en, HelloJob.new.serialize['locale']
+  end
+
+  test 'deserialize sets locale' do
+    job = HelloJob.new
+    job.deserialize 'locale' => :es
+    assert_equal :es, job.locale
+  end
+
+  test 'deserialize sets default locale' do
+    job = HelloJob.new
+    job.deserialize({})
+    assert_equal :en, job.locale
+  end
 end
diff --git a/activejob/test/cases/translation_test.rb b/activejob/test/cases/translation_test.rb
new file mode 100644
index 0000000000..d5e3aaf9e3
--- /dev/null
+++ b/activejob/test/cases/translation_test.rb
@@ -0,0 +1,20 @@
+require 'helper'
+require 'jobs/translated_hello_job'
+
+class TranslationTest < ActiveSupport::TestCase
+  setup do
+    JobBuffer.clear
+    I18n.available_locales = [:en, :de]
+    @job = TranslatedHelloJob.new('Johannes')
+  end
+
+  teardown do
+    I18n.available_locales = [:en]
+  end
+
+  test 'it performs the job in the given locale' do
+    @job.locale = :de
+    @job.perform_now
+    assert_equal "Johannes says Guten Tag", JobBuffer.last_value
+  end
+end
diff --git a/activejob/test/integration/queuing_test.rb b/activejob/test/integration/queuing_test.rb
index d345092dee..e1634972d1 100644
--- a/activejob/test/integration/queuing_test.rb
+++ b/activejob/test/integration/queuing_test.rb
@@ -68,4 +68,21 @@ class QueuingTest < ActiveSupport::TestCase
     refute delayed_test_job.provider_job_id.nil?,
       'Provider job id should by set for delayed jobs by provider'
   end
+
+  test 'current locale is kept while running perform_later' do
+    skip if adapter_is?(:inline)
+
+    begin
+      I18n.available_locales = [:en, :de]
+      I18n.locale = :de
+
+      TestJob.perform_later @id
+      wait_for_jobs_to_finish_for(5.seconds)
+      assert job_executed
+      assert_equal 'de', job_output
+    ensure
+      I18n.available_locales = [:en]
+      I18n.locale = :en
+    end
+  end
 end
diff --git a/activejob/test/jobs/translated_hello_job.rb b/activejob/test/jobs/translated_hello_job.rb
new file mode 100644
index 0000000000..9657cd3f54
--- /dev/null
+++ b/activejob/test/jobs/translated_hello_job.rb
@@ -0,0 +1,10 @@
+require_relative '../support/job_buffer'
+
+class TranslatedHelloJob < ActiveJob::Base
+  def perform(greeter = "David")
+    translations = { en: 'Hello', de: 'Guten Tag' }
+    hello        = translations[I18n.locale]
+
+    JobBuffer.add("#{greeter} says #{hello}")
+  end
+end
diff --git a/activejob/test/support/integration/dummy_app_template.rb b/activejob/test/support/integration/dummy_app_template.rb
index 09a68738ad..4ffdb8cffa 100644
--- a/activejob/test/support/integration/dummy_app_template.rb
+++ b/activejob/test/support/integration/dummy_app_template.rb
@@ -8,13 +8,17 @@ require "#{File.expand_path("../jobs_manager.rb",  __FILE__)}"
 JobsManager.current_manager.setup
 CODE
 
+initializer 'i18n.rb', <<-CODE
+I18n.available_locales = [:en, :de]
+CODE
+
 file 'app/jobs/test_job.rb', <<-CODE
 class TestJob < ActiveJob::Base
   queue_as :integration_tests
 
   def perform(x)
     File.open(Rails.root.join("tmp/\#{x}"), "w+") do |f|
-      f.write x
+      f.write I18n.locale
     end
   end
 end
diff --git a/activejob/test/support/integration/test_case_helpers.rb b/activejob/test/support/integration/test_case_helpers.rb
index 7e87ede275..39aee6d407 100644
--- a/activejob/test/support/integration/test_case_helpers.rb
+++ b/activejob/test/support/integration/test_case_helpers.rb
@@ -45,4 +45,8 @@ module TestCaseHelpers
     def job_executed
       Dummy::Application.root.join("tmp/#{@id}").exist?
     end
+
+    def job_output
+      File.read Dummy::Application.root.join("tmp/#{@id}")
+    end
 end
-- 
cgit v1.2.3