diff options
-rw-r--r-- | actionmailer/CHANGELOG.md | 7 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/base.rb | 17 | ||||
-rw-r--r-- | actionmailer/test/base_test.rb | 39 | ||||
-rw-r--r-- | activesupport/CHANGELOG.md | 7 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/object/json.rb | 6 | ||||
-rw-r--r-- | activesupport/test/core_ext/object/json_cherry_pick_test.rb | 42 | ||||
-rw-r--r-- | railties/CHANGELOG.md | 5 |
7 files changed, 119 insertions, 4 deletions
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 4e3a9daf7d..bcfde6d96f 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,10 @@ +* Raise an exception when attachments are added after `mail` was called. + This is a safeguard to prevent invalid emails. + + Fixes #16163. + + *Yves Senn* + * Add `config.action_mailer.show_previews` configuration option. This config option can be used to enable the mail preview in environments diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 048f2ddc35..d9b88ec608 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -649,7 +649,22 @@ module ActionMailer # mail.attachments[0] # => Mail::Part (first attachment) # def attachments - @_message.attachments + if @_mail_was_called + LateAttachmentsProxy.new(@_message.attachments) + else + @_message.attachments + end + end + + class LateAttachmentsProxy < SimpleDelegator + def inline; _raise_error end + def []=(_name, _content); _raise_error end + + private + def _raise_error + raise RuntimeError, "Can't add attachments after `mail` was called.\n" \ + "Make sure to use `attachments[]=` before calling `mail`." + end end # The main method that creates the message and renders the email templates. There are diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index 229ded8e04..6116d1e29f 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -232,6 +232,45 @@ class BaseTest < ActiveSupport::TestCase end end + test "adding attachments after mail was called raises exception" do + class LateAttachmentMailer < ActionMailer::Base + def welcome + mail body: "yay", from: "welcome@example.com", to: "to@example.com" + attachments['invoice.pdf'] = 'This is test File content' + end + end + + e = assert_raises(RuntimeError) { LateAttachmentMailer.welcome } + assert_match(/Can't add attachments after `mail` was called./, e.message) + end + + test "adding inline attachments after mail was called raises exception" do + class LateInlineAttachmentMailer < ActionMailer::Base + def welcome + mail body: "yay", from: "welcome@example.com", to: "to@example.com" + attachments.inline['invoice.pdf'] = 'This is test File content' + end + end + + e = assert_raises(RuntimeError) { LateInlineAttachmentMailer.welcome } + assert_match(/Can't add attachments after `mail` was called./, e.message) + end + + test "accessing attachments works after mail was called" do + class LateAttachmentAccessorMailer < ActionMailer::Base + def welcome + attachments['invoice.pdf'] = 'This is test File content' + mail body: "yay", from: "welcome@example.com", to: "to@example.com" + + unless attachments.map(&:filename) == ["invoice.pdf"] + raise Minitest::Assertion, "Should allow access to attachments" + end + end + end + + assert_nothing_raised { LateAttachmentAccessorMailer.welcome } + end + # Implicit multipart test "implicit multipart" do email = BaseMailer.implicit_multipart diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 02aea8d21f..2a53fa95c1 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,10 @@ +* Fixed a compatibility issue with the `Oj` gem when cherry-picking the file + `active_support/core_ext/object/json` without requiring `active_support/json`. + + Fixes #16131. + + *Godfrey Chan* + * Make `Hash#with_indifferent_access` copy the default proc too. *arthurnn*, *Xanders* diff --git a/activesupport/lib/active_support/core_ext/object/json.rb b/activesupport/lib/active_support/core_ext/object/json.rb index 5496692373..698b2d1920 100644 --- a/activesupport/lib/active_support/core_ext/object/json.rb +++ b/activesupport/lib/active_support/core_ext/object/json.rb @@ -162,7 +162,7 @@ end class Time def as_json(options = nil) #:nodoc: - if ActiveSupport.use_standard_json_time_format + if ActiveSupport::JSON::Encoding.use_standard_json_time_format xmlschema(ActiveSupport::JSON::Encoding.time_precision) else %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}) @@ -172,7 +172,7 @@ end class Date def as_json(options = nil) #:nodoc: - if ActiveSupport.use_standard_json_time_format + if ActiveSupport::JSON::Encoding.use_standard_json_time_format strftime("%Y-%m-%d") else strftime("%Y/%m/%d") @@ -182,7 +182,7 @@ end class DateTime def as_json(options = nil) #:nodoc: - if ActiveSupport.use_standard_json_time_format + if ActiveSupport::JSON::Encoding.use_standard_json_time_format xmlschema(ActiveSupport::JSON::Encoding.time_precision) else strftime('%Y/%m/%d %H:%M:%S %z') diff --git a/activesupport/test/core_ext/object/json_cherry_pick_test.rb b/activesupport/test/core_ext/object/json_cherry_pick_test.rb new file mode 100644 index 0000000000..2f7ea3a497 --- /dev/null +++ b/activesupport/test/core_ext/object/json_cherry_pick_test.rb @@ -0,0 +1,42 @@ +require 'abstract_unit' + +# These test cases were added to test that cherry-picking the json extensions +# works correctly, primarily for dependencies problems reported in #16131. They +# need to be executed in isolation to reproduce the scenario correctly, because +# other test cases might have already loaded additional dependencies. + +class JsonCherryPickTest < ActiveSupport::TestCase + include ActiveSupport::Testing::Isolation + + def test_time_as_json + require_or_skip 'active_support/core_ext/object/json' + + expected = Time.new(2004, 7, 25) + actual = Time.parse(expected.as_json) + + assert_equal expected, actual + end + + def test_date_as_json + require_or_skip 'active_support/core_ext/object/json' + + expected = Date.new(2004, 7, 25) + actual = Date.parse(expected.as_json) + + assert_equal expected, actual + end + + def test_datetime_as_json + require_or_skip 'active_support/core_ext/object/json' + + expected = DateTime.new(2004, 7, 25) + actual = DateTime.parse(expected.as_json) + + assert_equal expected, actual + end + + private + def require_or_skip(file) + require(file) || skip("'#{file}' was already loaded") + end +end diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index e9abfac7a0..651f40007e 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,8 @@ +* Scaffold generator `_form` partial adds `class="field"` for password + confirmation fields. + + *noinkling* + * Add `Rails::Application.config_for` to load a configuration for the current environment. |