Ruby most useful Hash methods
Tags: ruby, cleancode, softwaredevelopment, codenewbie
Published: 2024-03-24 18:07:45

Since almost everything in ruby is an object, you get tons of feature that makes data manipulation easier. Ruby hash is one of the data types and is easy to work with. And if you are looking to work with a key and value pair, the `hash` is the way to go. Here are some of the useful hash methods to know. 

### `Hash#fetch`
Fetch method allows you to retrieve a value from a hash using a key. If the key is not found in the hash, you can specify a default value to return instead of nil.

```rb
person = { "name" => "John", "age" => 30, "city" => "New York" }

person.fetch("name")
# John

# Provided default value is returned instead of nil
# when the value is not found
person.fetch("country", "Unknown")
# Unknown
```


### `Hash#dig`
dig method allows you to access nested values in a hash without having to check for the existence of each key in the chain. The dig method takes a list of keys as arguments and returns the value at the specified key path.

```rb
person = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main St",
    city: "New York",
    country: "USA"
  }
}

name = person.dig(:name)
city = person.dig(:address, :city)
country = person.dig(:address, :country)
state = person.dig(:address, :state)

# Name: John
# City: New York
# Country: USA
# State: nil
```


### `Hash#then`
then method, you can chain methods together and pass the result of one method to the next method as an argument. The then method is called on the object and takes a block as an argument. The block is called with the object as the argument, and the block's return value is the result of the method chain.

```rb
even_numbers = [2, 4, 6, 8, 10]

def add_ten_to_even_numbers(numbers)
  numbers.map { |num| num + 10 }
end

add_ten_to_even_numbers(even_numbers).then { |new_num| puts new_num.inspect }
# [12, 14, 16, 18, 20]
```


### `Hash#value?`
value? method allows you to check if a hash contains a specific value. The method returns true if the value is found in the hash, and false otherwise. This takes out the complexity of trying to loop through a hash. 

```rb
person = { name: "John", age: 30, city: "New York", country: "GH", code: "GH"}

hash.value?(30)
# true 

hash.value?(31)
# false

just an addon, values_at method allows you to retrieve the values of multiple keys from a hash.

hash.values_at(:age, :city, :country)
# [30, "New York", "GH"]

```


### `Hash#tap`
allows you to "tap into" a method chain, and do something with the object that is being passed along the chain. The block is called with the object as the argument and the block's return value is ignored.

```rb
valid_names = ["John", "Smith", "Jane", "Doe", "Mick", "Jagger", "Sam", "stone"]
guest_names = [ "Doe", "Jagger", "Khamil", "Paul"]

def check_guest_names(guest_names, valid_names)
  [].tap do |x|
    guest_names.each do |name|
      x << name if valid_names.include?(name)
    end
  end
end

response = check_guest_names(guest_names, valid_names)
puts response.inspect
# ["Doe", "Jagger"]

(1..10).to_a.select { |x| x.even? }.tap { |x| puts "Even #{x}" }
# Even [2, 4, 6, 8, 10]

```

***Hope it was helpful, and beware of the bang(!)***