Hash#slice
Hash#slice(*keys) → a_hash What It Does
Hash#slice gives you a way to grab just the key-value pairs you need from a hash. You tell it which keys you want, and it hands back a new hash containing only those pairs. Your original hash stays exactly as it was — slice does not change it.
Think of it like a buffet. You have a plate full of different foods, but you only want a few of them. You pick out what you want and put it on your own plate. The original plate (your original hash) still has everything on it.
Signature
# Syntax (not runnable code):
Hash#slice(*keys) → a_hash
The method accepts any number of key arguments using the splat operator (*). It returns a new Hash object.
Parameters
*keys— One or more keys to extract from the hash. You can pass as many keys as you need, separated by commas.
Return Value
The method returns a new Hash containing only the key-value pairs for keys that exist in the original hash. If none of the requested keys exist, you get an empty hash back. The original hash is never modified.
Basic Usage
With a single key:
config = { host: "localhost", port: 3000, debug: true }
config.slice(:host) # => {:host=>"localhost"}
config # => {:host=>"localhost", :port=>3000, :debug=>true}
The original config still contains all three keys after calling slice — the method is non-destructive.
You can request multiple keys at once:
data = { a: 100, b: 200, c: 300 }
data.slice(:a, :c) # => {:a=>100, :c=>300}
Handling Missing Keys
If you ask for a key that does not exist, slice simply ignores it. No error is raised.
user = { name: "Alice", email: "alice@example.com" }
user.slice(:name, :phone, :address)
# => {:name=>"Alice"}
The :phone and :address keys do not exist in the hash, so they are silently skipped. You only get back the pairs that actually exist.
Result Ordering
The order of the key-value pairs in the result matches the order in which you listed the keys in your argument list, not the order they appear in the original hash.
{ c: 3, a: 1, b: 2 }.slice(:b, :a, :c)
# => {:b=>2, :a=>1, :c=>3}
This can be useful when you need a predictable output order.
Common Use Cases
Parameter Whitelisting
A very common use case is restricting user input to only the keys your method accepts. This prevents unexpected or malicious keys from entering your system.
# Only allow these specific parameters
def create_user(params)
permitted = params.slice(:name, :email, :password)
# Now permitted contains only the keys you expect
end
user_input = { name: "Bob", email: "bob@test.com", role: "admin", token: "***" }
create_user(user_input)
# => {:name=>"Bob", :email=>"bob@test.com"}
Only the keys that exist in the original hash and are explicitly requested make it through. Keys that do not exist are silently ignored.
Extracting Config
When working with configuration hashes, you often want to pass only a subset of settings to another component:
app_config = { host: "0.0.0.0", port: 8080, workers: 4, log_level: "debug" }
server_config = app_config.slice(:host, :port)
# => {:host=>"0.0.0.0", :port=>8080}
Symbol Keys vs String Keys
Ruby distinguishes between symbol keys and string keys. {a: 1} and {"a" => 1} are completely different hashes. Calling slice with symbol keys on a string-keyed hash (or vice versa) returns an empty hash:
{"host" => "localhost"}.slice(:host)
# => {}
This matters when working with APIs or libraries that use one style exclusively.
Ruby 3 Keyword Arguments
In Ruby 3, hashes and keyword arguments are handled separately. If a method expects keyword arguments but receives a hash, slice alone will not convert between them:
def greet(name:, age:)
puts "Hello, #{name}!"
end
config = { name: "Alice", age: 30 }
# greet(config.slice(:name, :age)) # => TypeError: wrong arguments
To pass a sliced hash as keyword arguments, use the double-splat operator:
greet(**config.slice(:name, :age)) # => "Hello, Alice!"
Edge Cases
No Keys Given
Calling slice with no arguments returns an empty hash:
{a: 1, b: 2}.slice() # => {}
Empty Hash
If you call slice on an empty hash, you always get an empty hash back regardless of what keys you ask for:
{}.slice(:a, :b) # => {}
All Keys Missing
When none of the requested keys exist in the hash, you get an empty hash:
{ x: 1, y: 2 }.slice(:a, :b) # => {}
See Also
- Hash#reject — remove keys that match a condition
- Hash#select — keep entries that match a condition
- Hash#merge — combine hashes together