rubyguides

Hash#except

hash.except(*keys) -> hash

The except method returns a new hash with one or more specified keys removed. The original hash remains unchanged, making this a non-destructive operation. This method was introduced in Ruby 3.0 as part of the collection refinements.

Signature

hash.except(*keys) → new_hash

Parameters

ParameterTypeDescription
*keysSymbol, StringOne or more keys to exclude from the returned hash. Both symbol and string keys are supported.

Return Value

Returns a new Hash containing all key-value pairs from the original hash except those whose keys match the arguments.

Basic Usage

user = { name: 'Alice', email: 'alice@example.com', password: 'secret123', token: 'abc123' }

user.except(:password, :token)
# => {:name=>"Alice", :email=>"alice@example.com"}

The original hash stays unchanged:

user # => {:name=>"Alice", :email=>"alice@example.com", :password=>"secret123", :token=>"abc123"}

Excluding Multiple Keys

You can exclude as many keys as you need:

config = { host: 'localhost', port: 3000, debug: true, verbose: true, secret: 'key' }

config.except(:secret, :debug)
# => {:host=>"localhost", :port=>3000, :verbose=>true}

Symbol vs String Keys

Symbol and string keys are treated as distinct. Excluding :id does not remove 'id':

params = { id: 1, 'id' => 'two', name: 'Bob' }

params.except(:id)
# => {"id"=>"two", :name=>"Bob"}

params.except('id')
# => {:id=>1, :name=>"Bob"}

Common Use Case: Filtering Sensitive Data

A frequent application is removing sensitive attributes before logging or passing hashes to external services:

credentials = {
  username: 'alice',
  password: 'supersecret',
  api_key: 'sk-1234567890',
  name: 'Alice Smith'
}

safe_credentials = credentials.except(:password, :api_key)
safe_credentials
# => {:username=>"alice", :name=>"Alice Smith"}

This pattern prevents accidental exposure of secrets in logs or error reports:

def create_user(params)
  # Remove sensitive fields before logging
  safe_params = params.except(:password, :api_key)
  logger.info("Creating user: #{safe_params}")
  
  # ... rest of method
end

Chaining with Other Hash Methods

except returns a hash, so you can chain it with other hash methods:

data = { a: 1, b: 2, c: 3, d: 4, secret: 'hidden' }

data.except(:secret).select { |_k, v| v > 1 }
# => {:b=>2, :c=>3, :d=>4}

See Also

  • hash#slice — Returns a new hash containing only the specified keys (the inverse operation)
  • hash#transform_keys — Transform keys in a hash using a block or hash argument
  • hash#merge — Combine multiple hashes into a new hash