LaunchKit
All quizzes
Rails 0 views

When symbolize_keys collides :key and "key"

Question

What's the return value of the following Rails 7 code?

h = { key: 42, 'key' => 84 }

h.symbolize_keys # => ???

The correct answer is

Explanation

TL;DR

Hash#symbolize_keys (Active Support) builds a new hash where every key that responds to to_sym is converted to a symbol. Both :key and "key" map to the symbol :key, and a hash cannot hold the same key twice. The pairs are copied in insertion order, so "key" => 84 is written after key: 42 and overwrites it: the result is { key: 84 }.

Step by step

The snippets below run in any Ruby with Active Support loaded (require "active_support/all"), which is what a Rails app does for you.

require "active_support/all"

h = { key: 42, "key" => 84 }

h.symbolize_keys # => {key: 84}
h                # => {key: 42, "key" => 84}

symbolize_keys walks the pairs in insertion order and inserts each converted pair into a fresh hash:

  1. :key => 42 is inserted as :key => 42.
  2. "key" => 84 converts to :key => 84, which overwrites the existing :key entry.

The receiver is untouched; symbolize_keys! is the in-place variant.

Insertion order decides the winner. Flip the pairs and the symbol key wins instead:

require "active_support/all"

{ "key" => 84, key: 42 }.symbolize_keys # => {key: 42}

Edge cases

symbolize_keys is shallow. Nested hashes keep their string keys; deep_symbolize_keys converts all levels:

require "active_support/all"

{ a: { "b" => 1 } }.symbolize_keys        # => {a: {"b" => 1}}
{ "a" => { "b" => 1 } }.deep_symbolize_keys # => {a: {b: 1}}

In plain Ruby (2.5+), transform_keys does the same job without Active Support, with the same last-one-wins collision rule:

{ key: 42, "key" => 84 }.transform_keys(&:to_sym) # => {key: 84}

Share this quiz

Comments

No comments yet. Be the first.

Only used to confirm and publish your comment. Never shown publicly, never shared.

Markdown: **bold**, `code`, ```fenced blocks```, > quotes, [links](url). HTML and images are not rendered.