简体   繁体   中英

How to convert a find_by_sql hstore string to a hash in Ruby on Rails

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.

Try this

eval("{ #{deepthought} }")

It wraps the deepthought string with curly brace { }, and then use eval

A bit late but if you need to convert a multiple entries this works great.

def hstore_to_hash(hstore)
  values = {}
  hstore.gsub(/"/, '').split(",").each do |hstore_entry|
    each_element = hstore_entry.split("=>")
    values[each_element[0]] = each_element[1]
  end
  values
end

这似乎可行,但感觉很脏。

JSON.parse "{ #{deepthought} }".gsub('=>', ':')

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM