Как я могу встроить json в ruby/rails?

Я хотел бы пропустить синтаксический анализ некоторого json, возвращаемого моей БД, когда я просто сразу же снова превращаю его в json в ответ от моего приложения padrino.

т.е. у меня есть

get :data, provides: :json do
  Record.order(:day).map do |r|
    {r.day.to_s => JSON.parse!(r.data)}
  end.reduce({}, :merge!).to_json
end

и я хотел бы что-то вроде следующего (вдохновленный String#html_safe):

get :data, provides: :json do
  Record.order(:day).map do |r|
    {r.day.to_s => r.data.json_literal}
  end.reduce({}, :merge!).to_json
end

Я знаю, что могу переместить создание хэша в модель с помощью #as_json, но это не устраняет ненужное снижение производительности из-за синтаксического анализа и повторного кодирования json.

Пример вывода:

{
"2010-01-01":{"linux64":12186213,"mac":24131170},
"2010-01-02":{"linux":10650417,"mac":24139611,"win":12210218},
"2010-01-03":{"linux":10628353,"linux64":12184435,"win":12229263}
}

где объект, который является значением каждой пары ключ/значение, доступен в виде json-строки в r.data, например '{"linux":10650417,"mac":24139611,"win":12210218}', поэтому я хочу избежать синтаксического анализа r.data и просто встроить его.

Я попытался полностью обойти синтаксический анализ/дамп JSON со следующим:

get :data, provides: :json do
  "{"+Record.order(:day).map do |r|
    "\"#{r.day}\":#{r.data},"
  end.reduce(&:+).delete(' ').chop+"}"
end

но производительность была даже хуже, чем у версии с ненужным парсингом. (Что странно, я не уверен, что конкатенация строк медленная или интерполяция строк...)


person Camden Narzt    schedule 04.12.2014    source источник
comment
Вы можете показать ожидаемый результат?   -  person Зелёный    schedule 04.12.2014
comment
Я добавил сокращенную версию вопроса.   -  person Camden Narzt    schedule 04.12.2014


Ответы (1)


Оказывается, лучший способ сделать это — на уровне БД, поскольку postgres может встраивать столбцы json в объекты json и агрегировать строки намного быстрее, чем это может сделать ruby. Поэтому я сделал это и уменьшил задержку с 30 мс до 8 мс. Тело метода ниже:

Sequel::Model.db.fetch("select json_object_agg(day,data) as jsobj from records;").first[:jsobj]

Рекомендации:

person Camden Narzt    schedule 11.12.2014