aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionmailer/CHANGELOG.md7
-rw-r--r--actionmailer/lib/action_mailer/base.rb17
-rw-r--r--actionmailer/test/base_test.rb39
-rw-r--r--activesupport/CHANGELOG.md7
-rw-r--r--activesupport/lib/active_support/core_ext/object/json.rb6
-rw-r--r--activesupport/test/core_ext/object/json_cherry_pick_test.rb42
-rw-r--r--railties/CHANGELOG.md5
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.