We have recently migrated our codebase from Ruby 2.7.x and Rails 5.2.x to Ruby 3.2.2 and Rails 6.1.7.3. Previously, our mailers were defined like this:
class ApplicationMailer < ActionMailer::Base
...
end
class MyMailer < ApplicationMailer
def custom(user: , timestamp: Time.now)
@user = user
@timestamp = timestamp
end
end
And we would deliver emails like this: MyMailer.custom(user: @myuser).deliver_now
. With the update, this now returns an ArgumentError: wrong number of arguments (given 1, expected 0; required keyword: user) (ArgumentError)
.
We have found that we are supposed to pass the arguments in a params hash and read from there, but that seems pretty cumbersome and unelegant compared to our previous solution. So my questions are,
This is the way that we are apparently supposed to pass parameters:
class MyMailer < ApplicationMailer
def custom
@user = params[:user]
@timestamp = params[:timestamp] || Time.now
end
end
ActionMailer still accepts passing arguments on the mailer actions. Howevber, it appears that the keyword argument semantics in Ruby 3.2 are not fully expected by Rails 6.1 which causes the issue you are seeing.
Rails 6.1 was released before Ruby 3.2 was a thing. As recent Ruby releases have changed some semantics with keywords arguments, it's appears likely that Rails 6.1 is not (fully) compatible with Ruby 3.2.
While I have not found any authoritative documentation about this, for the latest commit on the Rails 6.1.7.3 tag, the actionmailer tests fail a test regarding keyword arguments with Ruby 3.2.
As such, you have two possible avenues to fix this issue:
As a quick fix, you could probably now first downgrade your Ruby version, then start upgading your Rails application further until you can bump your Ruby version again.