【问题标题】:How to convert a find_by_sql hstore string to a hash in Ruby on Rails如何在 Ruby on Rails 中将 find_by_sql hstore 字符串转换为哈希
【发布时间】:2014-05-14 15:37:43
【问题描述】:

这看起来非常简单,但我不知道如何将哈希字符串转换为哈希。

当我执行 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?,但还是想不通。

【问题讨论】:

  • 你的find_by_sql是什么样的?
  • 这是在一个大型 SQL 查询中。简化后类似于Answer.find_by_sql("SELECT answers.id AS aid, answers.deepthought AS deepthought FROM answers")
  • 我认为除非您可以升级到本机支持 hstore 数据类型的 Rails4,否则您会遇到不愉快的问题。你可以看看 Rails4 如何在驱动程序中解析 hstore 并模仿它。

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


【解决方案1】:

试试这个

eval("{ #{deepthought} }")

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

【讨论】:

  • 谢谢。我在链接的帖子上读到这有一些严重的安全风险。我无法控制此处插入的答案,似乎恶意用户可以插入 ruby​​。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    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 字符串以将它们解压缩为哈希。

    【讨论】:

    • 谢谢。这样干净多了。
    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 2012-07-13
      • 2014-09-24
      • 2010-11-05
      • 2017-06-02
      • 2014-04-30
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      • 2013-07-06
      相关资源
      最近更新 更多