Как преобразовать строку find_by_sql hstore в хеш в Ruby on Rails
Это кажется нелепо простым, но я не могу понять, как преобразовать хеш-строку в хеш.
Когда я делаю 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\\\"\""
Я видел, как я могу преобразовать объект String в объект Hash?, но я до сих пор не могу понять это.
4 ответа
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/
) и отправьте свои строки в hstore через это string_to_hstore
распаковать их в хеши.
Немного поздно, но если вам нужно конвертировать несколько записей, это прекрасно работает.
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
Попробуй это
eval("{ #{deepthought} }")
Оборачивает строку глубокой мысли фигурной скобкой { }, а затем использует eval
Кажется, это работает, но кажется грязным.
JSON.parse "{ #{deepthought} }".gsub('=>', ':')