Добавление вычисляемого столбца в запрос ActiveRecord

Я выполняю запрос с использованием области и некоторых условий. Что-то вроде этого:

conditions[:offset] = (options[:page].to_i - 1) * PAGE_SIZE unless options[:page].blank?    
conditions[:limit] = options[:limit] ||= PAGE_SIZE
scope = Promo.enabled.active
results = scope.all conditions 

Я хотел бы добавить вычисляемый столбец к запросу (в тот момент, когда я сейчас вызываю scope.all). Что-то вроде этого:

(ACOS (минимум (1, COS (0,71106459055501) * COS (-1.2915436464758) * COS (RADIANS (address.lat)) * COS (RADIANS (address.lng)) + COS (0,71106459055501) * SIN (-1.2915436464758) * COS (RADIANS (address.lat)) * SIN (RADIANS (address.lng)) + SIN (0.71106459055501) * SIN (RADIANS (address.lat)))) * * 3963.19) в качестве точного расстояния

Есть ли способ сделать это без использования find_by_sql и переписывания всего существующего запроса?

Спасибо!

1 ответ

Решение

Конечно, используйте это:

conditions = Hash.new
conditions[:select] = "#{Promo.quoted_table_name}.*, (ACOS(...)) AS accurate_distance")
conditions[:offset] = (options[:page].to_i - 1) * PAGE_SIZE unless options[:page].blank?    
conditions[:limit] = options[:limit] ||= PAGE_SIZE
scope = Promo.enabled.active
results = scope.all conditions 

Обратите внимание на новый:select - который сообщает ActiveRecord, какие столбцы вы хотите вернуть. Возвращенный объект в результатах будет иметь метод доступа #accurante_distance. К сожалению, ActiveRecord глуп и не сможет определить тип столбца. Вы всегда можете добавить метод:

class Promo
  def accurate_distance
    raise "Missing attribute" unless has_attribute?(:accurate_distance)
    read_attribute(:accurate_distance).to_f # or instantiate a BigDecimal
  end
end

Смотрите #has_attribute для деталей.

Другие вопросы по тегам