Hash Transformations in Ruby: index_by vs index_with
July 4, 2025
Ruby and Rails developers often appreciate how expressive and elegant the language is—especially when it comes to working with collections.
One of the lesser-known gems in Ruby’s Enumerable toolbox is the pair of methods: index_by and index_with. Both are incredibly powerful for transforming arrays into hashes in a clean, readable, and performant way—without manual loops or verbose logic.
Let’s break them down with real-world examples
index_by: Turn a collection into a hash keyed by a custom value
The index_by method is perfect when you have an array of objects and want to convert it into a hash, using a specific attribute or computed value as the key.
users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
]
users.index_by { |u| u[:id] }
# => { 1 => { id: 1, name: "Alice" }, 2 => { id: 2, name: "Bob" } }
Use case: Quickly creating lookup tables by ID, email, or any unique identifier.
Another handy use:
files = ["/tmp/test.txt", "/var/log/app.log"]
files.index_by { |path| File.basename(path) }
# => { "test.txt" => "/tmp/test.txt", "app.log" => "/var/log/app.log" }
index_with: Build a hash from existing keys
While index_by starts from values , index_with starts from keys and assigns values using a block.
names = ["Alice", "Bob"]
names.index_with { |name| name.length }
# => { "Alice" => 5, "Bob" => 3 }
Another concise example:
%w[red green blue].index_with(&:upcase)
# => { "red" => "RED", "green" => "GREEN", "blue" => "BLUE" }
And one that’s especially practical in real life:
sentence = "the quick brown fox jumps over the lazy dog"
words = sentence.split
words.uniq.index_with { |w| words.count(w) }
# => { "the"=>2, "quick"=>1, "brown"=>1, ... }
ActiveRecord Pro Tip
index_by is especially useful with ActiveRecord:
User.all.index_by(&:email)
# => { "alice@example.com" => #<User id: 1>, "bob@example.com" => #<User id: 2> }
This helps avoid N+1 queries and gives you a simple way to organize records for quick lookup.
When to Use What?
Both methods support writing expressive, readable, and functional-style Ruby. Once you start using them, you’ll likely find many opportunities to replace verbose logic with these elegant tools.
Have you used index_by or index_with in your projects? Do you have a favorite use case or a cool tip? Drop it in the comments—I’d love to see how others apply these patterns.
Top comments (0)