Ruby 3 adds new method Hash#except

Akhil Gautam

By Akhil Gautam

on November 11, 2020

This blog is part of our  Ruby 3.0 series.

Ruby 3 adds a new method, except, to the Hash class. Hash#except returns a hash excluding the given keys and their values.

Why do we need Hash#except?

At times, we need to print or log everything except some sensitive data. Let's say we want to print user details in the logs but not passwords.

Before Ruby 3 we could have achieved it in the following ways:

1
2irb(main):001:0> user_details = { name: 'Akhil', age: 25, address: 'India', password: 'T:%g6R' }
3
4# 1. Reject with a block and include?
5irb(main):003:0> puts user_details.reject { |key, _| key == :password }
6=> { name: 'Akhil', age: 25, address: 'India' }
7
8# 2. Clone the hash with dup, tap into it and delete that key/value from the clone
9irb(main):005:0> puts user_details.dup.tap { |hash| hash.delete(:password) }
10=> { name: 'Akhil', age: 25, address: 'India' }
11

We know that ActiveSupport already comes with Hash#except but for a simple Ruby application using ActiveSupport would be overkill.

Ruby 3

To make the above task easier and more explicit, Ruby 3 adds Hash#except to return a hash excluding the given keys and their values:

1
2irb(main):001:0> user_details = { name: 'Akhil', age: 25, address: 'India', password: 'T:%g6R' }
3irb(main):002:0> puts user_details.except(:password)
4=> { name: 'Akhil', age: 25, address: 'India' }
5
6irb(main):003:0> db_info = YAML.safe_load(File.read('./database.yml'))
7irb(main):004:0> puts db_info.except(:username, :password)
8=> { port: 5432, database_name: 'example_db_production' }
9

Check out the commit for more details. Discussion around it can be found here.