`ostruct` was being implictly required by the `json` gem. But once it
was upgraded, these tests failed to initialize `OpenStruct`.
While we're trying to remove `ostruct` usage in #51510, CI is currently
failing so I'm pushing these in the mean time.
Since #50715, there are cases where `ActiveJob::Arguments` is used
but not required anymore in the test environment. This could be a
test for a custom argument serializer.
One solution could be to add a require "active_job/arguments" in
all the usages, but that isn't a convention we follow in Rails.
Instead, let's register the autoload for `ActiveJob::Arguments` in
`active_job.rb` so that it's always available when needed.
It's possible since Rails 6 (3ea2857943dc294d7809930b4cc5b318b9c39577) to let the framework create Event objects, but the guides and docs weren't updated to lead with this example.
Manually instantiating an Event doesn't record CPU time and allocations, I've seen it more than once that people copy-pasting the example code get confused about these stats returning 0. The tests here show that - just like the apps I've worked on - the old pattern keeps getting copy-pasted.
In case of mail delivery errors, the old ActionMailer::LogSubscriber
erroneously logged a "Delivered mail ..." line.
With this change it checks the passed exception object and logs a
"Failed delivery of mail" line instead.
Co-authored-by: Christian Esser <c_esser@yahoo.de>
Fixes https://github.com/rails/rails/issues/48477
Using forms inside emails is not common, but it's possible, and it's also possible to share views between controllers and mailers. Currently if a controller sets a `default_form_builder` that's different from the global config, mailers that use the same views will not default to the same `FormBuilder`. To fix this, this PR adds a `default_form_builder` method for mailers that does the same thing as its controller sibling.
There are assertions that expected/actual arguments are passed in the
reversed order by mistake. Enabling the LiteralAsActualArgument rule
prevents this mistake from happening.
The existing tests were auto-corrected by rubocop with a bit of
indentation adjustment.
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
In #45752, a `:params` kwarg was added to `assert_enqueued_email_with`
so that mailer params and args could be specified simultaneously.
However, for backward compatibility, the old behavior of treating an
`:args` Hash as params was preserved. The result is that if both
`:params` and `:args` are specified and `:args` is a Hash, `:params` is
ignored.
This commit deprecates specifying params via `:args` (i.e. passing a
Hash to `:args`).
After the deprecated behavior is removed, it will be possible to pass
a Hash to `:args`, and the Hash will be treated as named args instead.
Support args/params proc matchers in `assert_enqueued_email_with` to
make it behave more like `assert_enqueued_with`.
Fix#46621.
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
The `deliver_later_queue_name` is already configurable on ActionMailer::Base,
however the value is inherited by all subclasses. Use a class-inheritable
attribute instead, so that subclasses can override.
Refs:
- https://github.com/rails/rails/pull/18587#issuecomment-324975192
Prior to this change, access to `params` on `ActionMailer::Base`
instances prior to being decorated by `ActionMailer::Parameterized.with`
calls results in a `NoMethodError`:
```
Error:
ParameterizedTest#test_degrade_gracefully_when_.with_is_not_called:
NoMethodError: undefined method `[]' for nil:NilClass
before_action { @inviter, @invitee = params[:inviter], params[:invitee] }
^^^^^^^^^^
```
This change modifies the `attr_accessor :params` to be an `attr_writer`
paired with a `params` method that assigns `@params` to an empty `Hash`
whenever it's accessed without being otherwise initialized.
This pattern is pretty common:
```ruby
assert_emails 1 do
post invite_user_path # ...
end
email = ActionMailer::Base.deliveries.last
assert_equal "You were invited!", email.subject
```
We can make it a bit nicer, by returning the email object from `assert_emails`. This is similar to how `assert_raises` returns the error so you can do additional checks on it. With this PR:
```ruby
email = assert_emails 1 do
post invite_user_path # ...
end
assert_equal "You were invited!", email.subject
```
If a single email is sent, a single `Mail::Message` is returned. If multiple emails were sent, an array is returned.
```ruby
emails = assert_emails 2 do
post invite_user_path # ...
end
emails.each do |email|
assert_equal "You were invited!", email.subject
end
```
The Mail gem changed format of the delivery method arguments for
sendmail from a string to an array of strings in this commit
7e1196bd29
As the settings are now a sendmail delivery method produces the
following error:
```
.../mail-2.8.0/lib/mail/network/delivery_methods/sendmail.rb:53:in `initialize': :arguments expected to be an Array of individual string args (ArgumentError)
```
This also updates the mail dependency since the new default won't work
with the older versions.
This commit adds `ActionMailer.deprecator` and replaces all usages of
`ActiveSupport::Deprecation.warn` in `actionmailer/lib` with
`ActionMailer.deprecator`.
Additionally, this commit adds `ActionMailer.deprecator` to
`Rails.application.deprecators` so that it can be configured via
settings such as `config.active_support.report_deprecations`.
This commit adds `ActionDispatch.deprecator` and replaces all usages of
`ActiveSupport::Deprecation.warn` in `actionpack/lib/action_dispatch`
with `ActionDispatch.deprecator`.
Additionally, this commit adds `ActionDispatch.deprecator` to
`Rails.application.deprecators` so that it can be configured via
settings such as `config.active_support.report_deprecations`.
We recently let a few very easy to avoid warnings get merged.
The root cause is that locally the test suite doesn't run in
verbose mode unless you explictly pass `-w`.
On CI warnings are enabled, but there is no reason to look at the
build output unless something is failing. And even if one wanted
to do that, that would be particularly work intensive since warnings
may be specific to a Ruby version etc.
Because of this I believe we should:
- Always run the test suite with warnings enabled.
- Raise an error if a warning is unexpected.
We've been using this pattern for a long time at Shopify both in private
and public repositories.
Rubinius has not been maintained since May 2020 and based on the
discussion at https://github.com/rails/rails/pull/44984 ,
I think we can remove Rubinius specific code from Rails.
* This is an attempt to make the assert_enqueued_email_with easier to implement.
* Update actionmailer/test/test_helper_test.rb
Fix spelling.
* Documenting additional tests
* Missing a closing "end"
* Renaming tests for consistency
* Updating name
* Naming and documentation
* Leaving original test unchanged
* Fix test name, add new test
* Add assert_enqueued_emails examples to Rails guide
* Add example to test_helper
* Tweaking the Rails guide (#3)
* Updating Rails guide for consistency.
Co-authored-by: Bry <bryan.hunt@hey.com>
Co-authored-by: Ron Shinall <81988008+ron-shinall@users.noreply.github.com>
Right now many helpers have to deal with two modes of operation to
capture view output.
The main one is to swap the `@output_buffer` variable with a new buffer.
But since some view implementations such as `builder` keep a reference
on the buffer they were initialized with, this doesn't always work.
So additionally, the various capturing helpers also record the buffer
length prior to executing the block, and then `slice!` the buffer back
to its original size.
This is wasteful and make the code rather unclear.
Now that `OutputBuffer` is a delegator, I'd like to refactor all this
so that:
- @output_buffer is no longer re-assigned
- A single OutputBuffer instance is used for the entire response rendering
- Instead capturing is done through `OutputBuffer#capture`
Once the above is achieved, it should allow us to enabled Erubi's
`:chain_appends` option and get some reduced template size and some
performance.
Not re-assigning `@output_buffer` will also allow template to access
the local variable instead of an instance variable, which is cheaper.
But more importantly, that should make the code easier to understand
and easier to be compatible with `StreamingBuffer`.
The word "Crazy" has long been associated with mental illness. While
there may be other dictionary definitions, it's difficult for some of us
to separate the word from the stigmatization, gaslighting, and bullying
that often comes along with it.
This commit replaces instances of the word with various alternatives. I
find most of these more focused and descriptive than what we had before.
- Action Mailer delivery job should modify their `perform` method
signature in order to receive the new payload that Action Mailer
sends.
Before:
```ruby
def perform(mailer, mail_method, delivery_method, *args)
end
```
After:
```ruby
def perform(mailer, mail_method, delivery_method, args:)
end
```
This new behaviour was introduced couple years ago in a attempt to
get rid of the necessity to have a different job for paramterized
mailers. A deprecation was introduced for custom jobs inheriting
from `ActionMailer::DeliveryJob` but for jobs that didn't it went
unnoticed.
The deprecated behaviour was supposed to be removed in Rails 6.1
but we couldn't and it got reverted https://github.com/rails/rails/pull/39257
This reverts commit 0f9249c93f402d276730fcfaba1ed1b876ee7c26.
Reverted because this wasn't warning in custom jobs and therefore
applications may have not seen the deprecation. We'll need to fix the
deprecation to warn for custom jobs so that applications can migrate.
In the past, we sometimes hit missing `Symbol#start_with?` and
`Symbol#end_with?`.
63256bc5d7a8e812964d
So I proposed `Symbol#start_with?` and `Symbol#end_with?` to allow duck
typing that methods for String and Symbol, then now it is available in
Ruby 2.7.
https://bugs.ruby-lang.org/issues/16348
Using `String#starts_with?` and `String#ends_with?` could not be gained
that conveniency, so it is preferable to not use these in the future.