Adding a computed column to an ActiveRecord query
I am running a query using a scope and some conditions. Something like this:
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
I'd like to add a computed column to the query (at the point when I'm now calling scope.all). Something like this:
(ACOS(least(1,COS(0.71106459055501)*COS(-1.2915436464758)*COS(RADIANS(addresses.lat))*COS(RADIANS(addresses.lng))+ COS(0.71106459055501)*SIN(-1.2915436464758)*COS(RADIANS(addresses.lat))*SIN(RADIANS(addresses.lng))+ SIN(0.71106459055501)*SIN(RADIANS(addresses.lat))))*3963.19) as accurate_distance
Is there a way to do that without just using find_by_sql and rewriting the whole existing query开发者_运维技巧?
Thanks!
Sure, use this:
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
Note the new :select - that tells ActiveRecord what columns you want returned. The returned object in results will have a #accurante_distance accessor. Unfortunately, ActiveRecord is dumb and won't be able to infer the column's type. You can always add a method:
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
See #has_attribute for details.
精彩评论