How to fix Ruby 2.7 warning: Using the last argument as keyword parameters is deprecated
After upgrading to Ruby 2.7, I started to see these warnings in my Rails server logs:
warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
In Ruby 2.7, the way it handles the positional arguments and keyword arguments is changed, aiming to provide a smooth transition to Ruby 3.
Understand the change
If you were passing a Hash as a keyword argument, now you'd need to update your code to use the double splat operator:
def avatar(user, size:)
end
options = { size: "medium" }
avatar(user, options) # => 💥 warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
avatar(user, **options) # => 👍 use double splat to explicitly convert a Hash into keyword argument
Let's look at another example where the keyword argument is used to as the last argument with a default value.
def buy(stuff, need_receipt: false)
puts "stuff: #{stuff}"
puts "need_receipt: #{need_receipt}"
end
buy(item: "burger")
# 💥 warning: Passing the keyword argument as the last hash parameter is deprecated
# => stuff: { :item => "burger" }
# => need_receipt: false
Here you'll need to add braces {} to explicitly pass a Hash object:
buy({ item: "burger" })
# => stuff: { item: "burger }
# => need_receipt: false
(Now it makes the code review a bit troublesome as now we can't blindly suggest removing the { }
from the single Hash parameter like before 😅)
The reason why the Ruby team made the change is because the automatic conversion "too complex and troublesome". It had caused confusions and many bug report tickets in the past. So now we as the developers need to code it explicitly.
Learn more from the official ruby doc: - Separation of positional and keyword arguments in Ruby 3.0
3 ways to suppress the warnings
Many gems have been updated to the newly recommended style. There is a PR in Rails as well, but as of now the change has not been released.
To temporarily suppress the warnings.
- Start the rails server with
RUBYOPT='-W:no-deprecated' rails s
- Set
export RUBYOPT='-W:no-deprecated'
in your bash/zsh profile - Set
Warning[:deprecated] = false
in your ruby code
If you are to use No.3 and put it in a Rails initializer, it'll affect all members so make sure that's your intention, and be sure to come back remove it when Rails and other gems have caught up with the warnings.
Update: be aware of the No.2 env var solution, you may bumped into a weird error.
Read more
Clap to support the author, help others find it, and make your opinion count.