diff options
-rw-r--r-- | Gemfile | 3 | ||||
-rw-r--r-- | Gemfile.lock | 12 | ||||
-rw-r--r-- | actionmailer/CHANGELOG.md | 6 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/delivery_job.rb | 6 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/message_delivery.rb | 2 | ||||
-rw-r--r-- | actionmailer/test/message_delivery_test.rb | 20 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/cookies.rb | 10 | ||||
-rw-r--r-- | actionpack/test/controller/caching_test.rb | 1 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/form_options_helper.rb | 12 | ||||
-rw-r--r-- | activejob/lib/active_job/arguments.rb | 21 | ||||
-rw-r--r-- | activejob/test/cases/argument_serialization_test.rb | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/calculations.rb | 5 | ||||
-rw-r--r-- | guides/source/action_mailer_basics.md | 18 | ||||
-rw-r--r-- | guides/source/action_view_overview.md | 12 | ||||
-rw-r--r-- | railties/lib/rails/generators/rails/app/app_generator.rb | 4 | ||||
-rw-r--r-- | railties/lib/rails/generators/rails/plugin/plugin_generator.rb | 4 | ||||
-rw-r--r-- | railties/test/generators/plugin_generator_test.rb | 2 | ||||
-rw-r--r-- | railties/test/generators/shared_generator_tests.rb | 2 |
18 files changed, 99 insertions, 48 deletions
@@ -5,6 +5,9 @@ gemspec # We need a newish Rake since Active Job sets its test tasks' descriptions. gem 'rake', '>= 10.3' +# Active Job depends on the URI::GID::MissingModelIDError, which isn't released yet. +gem 'globalid', github: 'rails/globalid' + # This needs to be with require false as it is # loaded after loading the test library to # ensure correct loading order diff --git a/Gemfile.lock b/Gemfile.lock index 2140881170..960a77af92 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -26,6 +26,13 @@ GIT arel (7.0.0.alpha) GIT + remote: git://github.com/rails/globalid.git + revision: 4df66fb9e9f0c832d29119aa8bc30be55a614b71 + specs: + globalid (0.3.5) + activesupport (>= 4.1.0) + +GIT remote: git://github.com/rails/jquery-rails.git revision: 272abdd319bb3381b23182b928b25320590096b0 branch: master @@ -138,8 +145,6 @@ GEM delayed_job (>= 3.0, < 4.1) erubis (2.7.0) execjs (2.3.0) - globalid (0.3.3) - activesupport (>= 4.1.0) hitimes (1.2.2) hitimes (1.2.2-x86-mingw32) i18n (0.7.0) @@ -272,6 +277,7 @@ DEPENDENCIES dalli (>= 2.2.1) delayed_job delayed_job_active_record + globalid! jquery-rails! json kindlerb (= 0.1.1) @@ -308,4 +314,4 @@ DEPENDENCIES w3c_validators BUNDLED WITH - 1.10.4 + 1.10.5 diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 7c1b0b215a..f325cbef81 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,9 @@ +* `deliver_later` now respects the current locale. + + Fixes #20774. + + *Johannes Opper* + * Add `config.action_mailer.deliver_later_queue_name` configuration to set the mailer queue name. diff --git a/actionmailer/lib/action_mailer/delivery_job.rb b/actionmailer/lib/action_mailer/delivery_job.rb index 52772af2d3..f008671a72 100644 --- a/actionmailer/lib/action_mailer/delivery_job.rb +++ b/actionmailer/lib/action_mailer/delivery_job.rb @@ -6,8 +6,10 @@ module ActionMailer class DeliveryJob < ActiveJob::Base # :nodoc: queue_as { ActionMailer::Base.deliver_later_queue_name } - def perform(mailer, mail_method, delivery_method, *args) #:nodoc: - mailer.constantize.public_send(mail_method, *args).send(delivery_method) + def perform(mailer, mail_method, delivery_method, locale, *args) #:nodoc: + I18n.with_locale(locale) do + mailer.constantize.public_send(mail_method, *args).send(delivery_method) + end end end end diff --git a/actionmailer/lib/action_mailer/message_delivery.rb b/actionmailer/lib/action_mailer/message_delivery.rb index ff2cb0fd01..c2479bf651 100644 --- a/actionmailer/lib/action_mailer/message_delivery.rb +++ b/actionmailer/lib/action_mailer/message_delivery.rb @@ -87,7 +87,7 @@ module ActionMailer private def enqueue_delivery(delivery_method, options={}) - args = @mailer.name, @mail_method.to_s, delivery_method.to_s, *@args + args = @mailer.name, @mail_method.to_s, delivery_method.to_s, I18n.locale.to_s, *@args ActionMailer::DeliveryJob.set(options).perform_later(*args) end end diff --git a/actionmailer/test/message_delivery_test.rb b/actionmailer/test/message_delivery_test.rb index 862ce26187..7ee4b01067 100644 --- a/actionmailer/test/message_delivery_test.rb +++ b/actionmailer/test/message_delivery_test.rb @@ -57,20 +57,20 @@ class MessageDeliveryTest < ActiveSupport::TestCase end test 'should enqueue the email with :deliver_now delivery method' do - assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3]) do + assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 'en', 1, 2, 3]) do @mail.deliver_later end end test 'should enqueue the email with :deliver_now! delivery method' do - assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now!', 1, 2, 3]) do + assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now!', 'en', 1, 2, 3]) do @mail.deliver_later! end end test 'should enqueue a delivery with a delay' do travel_to Time.new(2004, 11, 24, 01, 04, 44) do - assert_performed_with(job: ActionMailer::DeliveryJob, at: Time.current.to_f+600.seconds, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3]) do + assert_performed_with(job: ActionMailer::DeliveryJob, at: Time.current.to_f+600.seconds, args: ['DelayedMailer', 'test_message', 'deliver_now', 'en', 1, 2, 3]) do @mail.deliver_later wait: 600.seconds end end @@ -78,20 +78,28 @@ class MessageDeliveryTest < ActiveSupport::TestCase test 'should enqueue a delivery at a specific time' do later_time = Time.now.to_f + 3600 - assert_performed_with(job: ActionMailer::DeliveryJob, at: later_time, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3]) do + assert_performed_with(job: ActionMailer::DeliveryJob, at: later_time, args: ['DelayedMailer', 'test_message', 'deliver_now', 'en', 1, 2, 3]) do @mail.deliver_later wait_until: later_time end end test 'should enqueue the job on the correct queue' do - assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3], queue: "test_queue") do + assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 'en', 1, 2, 3], queue: "test_queue") do @mail.deliver_later end end test 'can override the queue when enqueuing mail' do - assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 1, 2, 3], queue: "another_queue") do + assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 'en', 1, 2, 3], queue: "another_queue") do @mail.deliver_later(queue: :another_queue) end end + + test 'should enqueue a delivery with the correct locale' do + I18n.with_locale('de') do + assert_performed_with(job: ActionMailer::DeliveryJob, args: ['DelayedMailer', 'test_message', 'deliver_now', 'de', 1, 2, 3]) do + @mail.deliver_later + end + end + end end diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index dd1f140051..9a1e2bd45c 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -8,7 +8,7 @@ require 'active_support/json' module ActionDispatch class Request < Rack::Request def cookie_jar - env['action_dispatch.cookies'] ||= Cookies::CookieJar.build(self) + env['action_dispatch.cookies'] ||= Cookies::CookieJar.build(env, host, ssl?, cookies) end end @@ -228,16 +228,12 @@ module ActionDispatch } end - def self.build(request) - env = request.env + def self.build(env, host, secure, cookies) key_generator = env[GENERATOR_KEY] options = options_for_env env - host = request.host - secure = request.ssl? - new(key_generator, host, secure, options).tap do |hash| - hash.update(request.cookies) + hash.update(cookies) end end diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index f21dd87400..4f5af85fea 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -381,6 +381,7 @@ class AutomaticCollectionCacheTest < ActionController::TestCase @controller.perform_caching = true @controller.partial_rendered_times = 0 @controller.cache_store = ActiveSupport::Cache::MemoryStore.new + ActionView::PartialRenderer.collection_cache = @controller.cache_store end def test_collection_fetches_cached_views diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index 1b7b188d65..8e729b3c39 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -35,8 +35,8 @@ module ActionView # <select name="post[person_id]" id="post_person_id"> # <option value="">None</option> # <option value="1">David</option> - # <option value="2" selected="selected">Sam</option> - # <option value="3">Tobias</option> + # <option value="2" selected="selected">Eileen</option> + # <option value="3">Rafael</option> # </select> # # * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string. @@ -48,8 +48,8 @@ module ActionView # <select name="post[person_id]" id="post_person_id"> # <option value="">Select Person</option> # <option value="1">David</option> - # <option value="2">Sam</option> - # <option value="3">Tobias</option> + # <option value="2">Eileen</option> + # <option value="3">Rafael</option> # </select> # # * <tt>:index</tt> - like the other form helpers, +select+ can accept an <tt>:index</tt> option to manually set the ID used in the resulting output. Unlike other helpers, +select+ expects this @@ -112,8 +112,8 @@ module ActionView # <select name="post[person_id]" id="post_person_id"> # <option value=""></option> # <option value="1" selected="selected">David</option> - # <option value="2">Sam</option> - # <option value="3">Tobias</option> + # <option value="2">Eileen</option> + # <option value="3">Rafael</option> # </select> # # assuming the associated person has ID 1. diff --git a/activejob/lib/active_job/arguments.rb b/activejob/lib/active_job/arguments.rb index cdb37879b6..8e462bfe5d 100644 --- a/activejob/lib/active_job/arguments.rb +++ b/activejob/lib/active_job/arguments.rb @@ -16,13 +16,13 @@ module ActiveJob end end - # Raised when an unsupported argument type is being set as job argument. We + # Raised when an unsupported argument type is set as a job argument. We # currently support NilClass, Fixnum, Float, String, TrueClass, FalseClass, - # Bignum and object that can be represented as GlobalIDs (ex: Active Record). - # Also raised if you set the key for a Hash something else than a string or - # a symbol. - class SerializationError < ArgumentError - end + # Bignum and objects that can be represented as GlobalIDs (ex: Active Record). + # Raised if you set the key for a Hash something else than a string or + # a symbol. Also raised when trying to serialize an object which can't be + # identified with a Global ID - such as an unpersisted Active Record model. + class SerializationError < ArgumentError; end module Arguments extend self @@ -59,7 +59,7 @@ module ActiveJob when *TYPE_WHITELIST argument when GlobalID::Identification - { GLOBALID_KEY => argument.to_global_id.to_s } + convert_to_global_id_hash(argument) when Array argument.map { |arg| serialize_argument(arg) } when ActiveSupport::HashWithIndifferentAccess @@ -147,5 +147,12 @@ module ActiveJob end end end + + def convert_to_global_id_hash(argument) + { GLOBALID_KEY => argument.to_global_id.to_s } + rescue URI::GID::MissingModelIdError + raise SerializationError, "Unable to serialize #{argument.class} " \ + "without an id. (Maybe you forgot to call save?)" + end end end diff --git a/activejob/test/cases/argument_serialization_test.rb b/activejob/test/cases/argument_serialization_test.rb index 8b9b62190f..933972a52b 100644 --- a/activejob/test/cases/argument_serialization_test.rb +++ b/activejob/test/cases/argument_serialization_test.rb @@ -88,6 +88,13 @@ class ArgumentSerializationTest < ActiveSupport::TestCase assert_equal "Job with argument: 2", JobBuffer.last_value end + test 'raises a friendly SerializationError for records without ids' do + err = assert_raises ActiveJob::SerializationError do + ActiveJob::Arguments.serialize [Person.new(nil)] + end + assert_match 'Unable to serialize Person without an id.', err.message + end + private def assert_arguments_unchanged(*args) assert_arguments_roundtrip args diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index df72ba7e9c..0f6015fa93 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -139,7 +139,7 @@ module ActiveRecord # # SELECT people.id, people.name FROM people # # => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']] # - # Person.uniq.pluck(:role) + # Person.distinct.pluck(:role) # # SELECT DISTINCT role FROM people # # => ['admin', 'member', 'guest'] # @@ -195,7 +195,8 @@ module ActiveRecord def perform_calculation(operation, column_name) operation = operation.to_s.downcase - # If #count is used with #distinct / #uniq it is considered distinct. (eg. relation.distinct.count) + # If #count is used with #distinct (i.e. `relation.distinct.count`) it is + # considered distinct. distinct = self.distinct_value if operation == "count" diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md index 6f159b2fc4..c31b50fcfc 100644 --- a/guides/source/action_mailer_basics.md +++ b/guides/source/action_mailer_basics.md @@ -533,6 +533,24 @@ url helper. NOTE: non-`GET` links require [jQuery UJS](https://github.com/rails/jquery-ujs) and won't work in mailer templates. They will result in normal `GET` requests. +### Adding images in Action Mailer Views + +Unlike controllers, the mailer instance doesn't have any context about the +incoming request so you'll need to provide the `:asset_host` parameter yourself. + +As the `:asset_host` usually is consistent across the application you can +configure it globally in config/application.rb: + +```ruby +config.action_mailer.asset_host = 'http://example.com' +``` + +Now you can display an image inside your email. + +```ruby +<%= image_tag 'image.jpg' %> +``` + ### Sending Multipart Emails Action Mailer will automatically send multipart emails if you have different diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md index 3c1c3c7873..98c6cbd540 100644 --- a/guides/source/action_view_overview.md +++ b/guides/source/action_view_overview.md @@ -1059,14 +1059,6 @@ If `@article.author_ids` is [1], this would return: <input name="article[author_ids][]" type="hidden" value="" /> ``` -#### country_options_for_select - -Returns a string of option tags for pretty much any country in the world. - -#### country_select - -Returns select and option tags for the given object and method, using country_options_for_select to generate the list of option tags. - #### option_groups_from_collection_for_select Returns a string of `option` tags, like `options_from_collection_for_select`, but groups them by `optgroup` tags based on the object relationships of the arguments. @@ -1153,8 +1145,8 @@ If `@article.person_id` is 1, this would become: <select name="article[person_id]"> <option value=""></option> <option value="1" selected="selected">David</option> - <option value="2">Sam</option> - <option value="3">Tobias</option> + <option value="2">Eileen</option> + <option value="3">Rafael</option> </select> ``` diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 4b73313388..b813b083f4 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -356,7 +356,9 @@ module Rails if app_const =~ /^\d/ raise Error, "Invalid application name #{app_name}. Please give a name which does not start with numbers." elsif RESERVED_NAMES.include?(app_name) - raise Error, "Invalid application name #{app_name}. Please give a name which does not match one of the reserved rails words: #{RESERVED_NAMES}" + raise Error, "Invalid application name #{app_name}. Please give a " \ + "name which does not match one of the reserved rails " \ + "words: #{RESERVED_NAMES.join(", ")}" elsif Object.const_defined?(app_const_base) raise Error, "Invalid application name #{app_name}, constant #{app_const_base} is already in use. Please choose another application name." end diff --git a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index 7f5bf0c8b8..66111004aa 100644 --- a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -364,7 +364,9 @@ task default: :test elsif camelized =~ /^\d/ raise Error, "Invalid plugin name #{original_name}. Please give a name which does not start with numbers." elsif RESERVED_NAMES.include?(name) - raise Error, "Invalid plugin name #{original_name}. Please give a name which does not match one of the reserved rails words: #{RESERVED_NAMES}" + raise Error, "Invalid plugin name #{original_name}. Please give a " \ + "name which does not match one of the reserved rails " \ + "words: #{RESERVED_NAMES.join(", ")}" elsif Object.const_defined?(camelized) raise Error, "Invalid plugin name #{original_name}, constant #{camelized} is already in use. Please choose another plugin name." end diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index d6e5f4bd89..73e68863f4 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -38,7 +38,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_equal "Invalid plugin name 43things. Please give a name which does not start with numbers.\n", content content = capture(:stderr){ run_generator [File.join(destination_root, "plugin")] } - assert_equal "Invalid plugin name plugin. Please give a name which does not match one of the reserved rails words: [\"application\", \"destroy\", \"plugin\", \"runner\", \"test\"]\n", content + assert_equal "Invalid plugin name plugin. Please give a name which does not match one of the reserved rails words: application, destroy, plugin, runner, test\n", content content = capture(:stderr){ run_generator [File.join(destination_root, "Digest")] } assert_equal "Invalid plugin name Digest, constant Digest is already in use. Please choose another plugin name.\n", content diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index f983b45d2b..77372fb514 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -56,7 +56,7 @@ module SharedGeneratorTests reserved_words = %w[application destroy plugin runner test] reserved_words.each do |reserved| content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] } - assert_match(/Invalid \w+ name #{reserved}. Please give a name which does not match one of the reserved rails words: \["application", "destroy", "plugin", "runner", "test"\]\n/, content) + assert_match(/Invalid \w+ name #{reserved}. Please give a name which does not match one of the reserved rails words: application, destroy, plugin, runner, test\n/, content) end end |