1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ActiveSupportのsymbolize_keys!が挙動不審だった件

Last updated at Posted at 2019-04-09

はじめに

StringとSymbolで同一名のKeyを持つHashはやめよう

{'id' => 10, :id => 11, 'name' => 'AAA', :name => 'BBB'}

遭遇

ruby2.4+rails
Hash.transform_keys!が特定の状況でsymbolize_keys(非破壊)と互換のない挙動をする

ruby2.5.2+rails
ruby2.5で同関数が実装された事で正常に動作する

確認

ruby2.4+rails

symbolが先の場合

[1] pry(main)> {:id => 10, 'id' => 11, :name => 'AAA', 'name' => 'BBB'}.symbolize_keys
=> {:id=>11, :name=>"BBB"}
[2] pry(main)> {:id => 10, 'id' => 11, :name => 'AAA', 'name' => 'BBB'}.symbolize_keys!
=> {:id=>11, :name=>"BBB"}

symbolが後の場合

[1] pry(main)> {'id' => 10, :id => 11, 'name' => 'AAA', :name => 'BBB'}.symbolize_keys
=> {:id=>11, :name=>"BBB"}
[2] pry(main)> {'id' => 10, :id => 11, 'name' => 'AAA', :name => 'BBB'}.symbolize_keys!
=> {:id=>10, :name=>"AAA"}

ruby2.5.2+rails

symbolが先の場合

[1] pry(main)> {:id => 10, 'id' => 11, :name => 'AAA', 'name' => 'BBB'}.symbolize_keys
=> {:id=>11, :name=>"BBB"}
[2] pry(main)> {:id => 10, 'id' => 11, :name => 'AAA', 'name' => 'BBB'}.symbolize_keys!
=> {:id=>11, :name=>"BBB"}

symbolが後の場合

[1] pry(main)> {'id' => 10, :id => 11, 'name' => 'AAA', :name => 'BBB'}.symbolize_keys
=> {:id=>11, :name=>"BBB"}
[2] pry(main)> {'id' => 10, :id => 11, 'name' => 'AAA', :name => 'BBB'}.symbolize_keys!
=> {:id=>11, :name=>"BBB"}

原因

該当箇所はここ
self[yield(key)] = delete(key)の部分、
'id'で取得した物を:idに対して代入し、symbolで保持していた値が失われている為。

def transform_keys!
  return enum_for(:transform_keys!) { size } unless block_given?
  keys.each do |key|
    self[yield(key)] = delete(key)
  end
  self
end

def symbolize_keys!
  transform_keys! { |key| key.to_sym rescue key }
end

おわりに

StringとSymbolで同一名のKeyを持つHashはやめよう

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?