Функция SQL в arel select без создания экземпляра активной записи

Я хочу получить результат SQL в виде хэша из ::ActiveRecord_Relation, потому что создание реальных объектов ActiveRecord выполняется очень медленно. Обычно я использую pluck, а затем заархивирую результат в хэш:

keys = [:name, :created_at]
hash = relation.pluck(*keys).map{|row| Hash[*keys.zip(row).flatten]}

Но запрос, который мне нужен, имеет функцию SQL, например:

SELECT name, UNIX_TIMESTAMP(created_at) - 3600 as hour_before_created FROM ...

Я могу сделать это, используя select Ареля:

rel = rel.select("name", "UNIX_TIMESTAMP(created_at) - 3600 as hour_before_created)")
hash = rel.as_json(except: :id)

Что дает правильный вывод, но, к сожалению, создает экземпляры объектов ActiveRecord.

Каков правильный способ получить хэш с соответствующими заголовками из каждого предложения as без создания экземпляров объектов ActiveRecord?


person Andrew Cone    schedule 19.01.2015    source источник


Ответы (1)


Я сделал это; это не красиво, но это работает. Самый простой способ сделать что-то подобное - создать связь ActiveRecord, но вместо запроса к базе данных вызвать для нее to_sql. Затем выполните:

ActiveRecord::Base.connection.execute(sql)

(Это не в моей голове; поправки приветствуются)

Это возвращает массив, который вы можете заархивировать с помощью Model.column_names или массив любых столбцов, которые вы фактически выбрали.

Не знаю, как использовать to_sql на Arel, но думаю, что это возможно.

person evanbikes    schedule 19.01.2015
comment
Я думаю, вы имеете в виду zip с res.fields, где res - это Mysql2::Result from execute: sql = rel.select("name", "UNIX_TIMESTAMP(created_at) - 3600 as hour_before_created)"); res = ActiveRecord::Base.connection.execute(sql); hash = res.to_a.map{|row| Hash[*res.fields.zip(row).flatten]} Это работает для меня. - person Andrew Cone; 20.01.2015