La razón por la que esto sucede es porque el método promedio está en ActiveRecord::Relation
, no en Arel, lo que obliga al cálculo.
m = Review.where('id = ?', 42).method(:average)
#=> #<Method: ActiveRecord::Relation(ActiveRecord::Calculations)#average>
m.source_location # or m.__file__ if you're on a different version of Ruby
#=> ["/Users/jtran/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.0.4/lib/active_record/relation/calculations.rb", 65]
Por el control de la parte interna de ActiveRecord::Calculations
, puede derivar cómo conseguir en el SQL que se utiliza.
my_reviewed_user_id = 42
relation = Review.where('reviewed_user_id = ?', my_reviewed_user_id)
column = Arel::Attribute.new(Review.unscoped.table, :stars)
relation.select_values = [column.average]
relation.to_sql
#=> "SELECT AVG(\"reviews\".\"stars\") AS avg_id FROM \"reviews\" WHERE (reviewed_user_id = 42)"
Cuidado si está trabajando en la consola. ActiveRecord::Relation
guarda en caché las cosas así que si escribe lo anterior en la consola línea por línea, en realidad no funcionará, porque la impresión bonita fuerza la relación. Sin embargo, la separación de lo anterior con punto y coma y sin líneas nuevas funcionará.
Alternativamente, se puede utilizar directamente Arel, así:
my_reviewed_user_id = 42
reviews = Arel::Table.new(:reviews)
reviews.where(reviews[:reviewed_user_id].eq(my_reviewed_user_id)).project(reviews[:stars].average).to_sql
#=> "SELECT AVG(\"reviews\".\"stars\") AS avg_id FROM \"reviews\" WHERE \"users\".\"reviewed_user_id\" = 42"
Super! Gracias por compartir el método que utilizó para resolver esto ... ¡será útil en el futuro! – Zabba
Es por eso que amo a Ruby. Siempre puedes pedir el REPL y la fuente. ¡Es la fuente en más de un sentido de la palabra! –
Esto me ayuda mucho en muchas lógicas diferentes. gran hombre de trabajo. –