[Ruby] Cookieのvalueにhashを使う(StringをHashに変更する)方法
問題点
- Cookieの:valueにHashをいれても、取り出すときにStringになってしまう
先日のブログで書いたとおり、セッション毎に別々のexpire timeを持たせるためにcookieを利用することにした.portaltan.hatenablog.com
・・・が、cookieの:valueにはHashが入らなかった(全部Stringに変換されてしまう)
response.set_cookie(:key, :value => {'first_value' => '1banme', 'second_value' => 2}) h = request.cookies['key'] logger.info h.class # => String logger.info h.size # => 44 logger.info h.kind_of?(Hash) # => nil logger.info h # => {"first_value"=>"1banme", "second_value"=>2}
解決法
取り出すときにStringをHashに戻すメソッドを書いた
def revert_hash_from_string(str) if str[0] != '{' raise "Unexpected style" end str = str.chomp.gsub(/"|^{|}$/, '') str = str.split(/,[\s]*|=>/) str.each_with_index{|column, idx| str[idx] = column.to_i if column =~ /^\d+$/ } Hash[*str] end
手順としては
- 引数がHashスタイルの文字列じゃない場合はException
- まずは文字列にはいっている文字列を囲む「"」と先頭の「{」と末尾の「}」を削る
- 次にスペースで区切って配列にする
- valueが数字だけで構成されている場合はInt型に変換する
- 上記のArrayを展開してHashにして返す
確認
response.set_cookie(:key, :value => {'first_value' => '1banme', 'second_value' => 2}) h = revert_hash_from_string(request.cookies['key']) logger.info h.class # => Hash logger.info h.size # => 2 logger.info h.kind_of?(Hash) # => true logger.info h # => {"first_value"=>"1banme", "second_value"=>2} logger.info h['first_value'] # => 1banme logger.info h['first_value'].class # => String logger.info h['second_value'] # => 2 logger.info h['second_value'].class # => Fixnum
強引なやり方だがとりあえずこれで行こうと思う。
(前のエントリーも含めてもっといい方法があれば教えて欲しいです。。)