This seems ludicrously simple but I cannot figure out how to convert a hash-string to a hash.
When I do a Answer.find_by_sql I get a string like this
deepthought = "\"answertolife\"=>\"42\""
But I cannot figure out how to turn that into a hash.
I have tried:
pry(main)> Hash[deepthought]
ArgumentError: odd number of arguments for Hash
pry(main)> JSON.parse deepthought
JSON::ParserError: 757: unexpected token at '"answertolife"=>"42"'
pry(main)> deepthought.to_json
=> "\"\\\"answertolife\\\"=>\\\"42\\\"\""
I saw How do I convert a String object into a Hash object?, but I still cannot figure it out.
Rails4 supports hstore out of the box so I'd probably handle the string casting the same way Rails4 does it. If you look inside the Rails4 PostgreSQL-specific casting code, you'll find string_to_hstore
:
def string_to_hstore(string)
if string.nil?
nil
elsif String === string
Hash[string.scan(HstorePair).map { |k, v|
v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
[k, v]
}]
else
string
end
end
and a little lower down in the same file, you'll find HstorePair
:
HstorePair = begin
quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
/(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
end
Stash that somewhere convenient (probably somewhere in lib/
) and send your hstore strings through that string_to_hstore
to unpack them into Hashes.