如何将find_by_sql hstore字符串转换为Ruby on Rails中的哈希

时间:2014-04-03 02:50:08

标签: ruby-on-rails postgresql ruby-on-rails-3.2 hstore

这看起来很简单但我无法弄清楚如何将哈希字符串转换为哈希。

当我做一个Answer.find_by_sql时,我得到一个像这样的字符串

deepthought = "\"answertolife\"=>\"42\""

但我无法弄清楚如何将其变成哈希。

我试过了:

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\\\"\""

我看到How do I convert a String object into a Hash object?,但我仍然无法理解。

4 个答案:

答案 0 :(得分:1)

试试这个

eval("{ #{deepthought} }")

用大括号{}包装deepthought字符串,然后使用eval

答案 1 :(得分:1)

有点晚了,但是如果您需要转换多个条目,那么效果很好。

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

答案 2 :(得分:0)

这似乎有效,但感觉很脏。

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

答案 3 :(得分:0)

Rails4支持hstore开箱即用,所以我可能会按照Rails4的方式处理字符串。如果查看Rails4 PostgreSQL特定的转换代码,你会发现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

在同一个文件中稍微低一点,您会找到HstorePair

HstorePair = begin
  quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
  unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
  /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
end

存放在方便的地方(可能在lib/中的某处)并通过string_to_hstore发送hstore字符串以将其解压缩为Hashes。