rubyguides

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