Hash#except in Ruby 3+
This was the tip of the week in the January 6, 2022 Ruby Weekly Newsletter.
If you’re an avid Rails user, you might be familiar with ActiveSupport’s Hash#except
which has been around for roughly 15 years. As of Ruby 3.0, Hash#except
is now a native Ruby method too!
But… what does it do? Hash#except gives us a hash excluding all of the keys we’ve passed as arguments. Let’s look at an example:
jemma = { name: "Jemma", username: "jemma", password: "super secure" }
jemma.except(:password)
# => { name: "Jemma", username: "jemma" }
Before Ruby 3.0, if we were in a repo which wasn’t using Rails, we could have done something like this:
jemma = { name: "Jemma", username: "jemma", password: "super secure" }
jemma.reject { |k,_| k == :password }
# => { name: "Jemma", username: "jemma" }
While this works totally fine, it gets a little clunky if we’re trying to exclude multiple different keys. Yet Hash#except
can also take multiple arguments:
jemma = { name: "Jemma", username: "jemma", password: "super secure" }
jemma.except(:name, :password)
# => { username: "jemma" }
Hash#except
might look familiar because it’s the inverse of Hash#slice. Hash#slice
will give us a hash containing key / value pairs whose keys we specify as arguments, while Hash#except
will give us a hash containing key / value pairs whose keys we don’t specify as arguments.
We might be wondering, what happens if we pass a key that is not in the hash?
jemma = { name: "Jemma", username: "jemma", password: "super secure" }
jemma.except("key doesn't exist")
# => { name: "Jemma", username: "jemma", password: "super secure" }
In this case, Ruby is technically still excluding this key from our hash - it just never appeared in the hash to begin with. (This is the same behavior as Hash#slice
.)