4

私は仮想属性のようなものを求めていますが、それはデータベースレベルで機能します。たとえば、フィールドがあり、に等しいage「仮想フィールド」を追加したいとしますが、次のように言うことができます:age_quintileage/5

Person.select(:age_quintile,"agv(height)").
  group(:age_quintile).
  order(:age_quintile)

対応する:

  SELECT (age/5) as age_quintile, avg(height) 
    FROM persons 
GROUP BY (age/5) 
ORDER BY (age/5);

また

Person.maximum(:age_quintile)

対応する

SELECT max(age/5) 
  FROM persons;

したがって、次のように、モデルでそのような属性を宣言すると思います。

class Person < ActiveRecord::Base
  ...
  magic_attribute :age_quintile, :integer, 'age/5'

end

ここで、最後のビットは SQL 式であり、型は文字列からキャストするために必要です。

バニラのActiveRecordまたはgemでそれを行う方法はありますか?

アップデート

モデルでそのような属性を宣言し、提案されているように、select でエイリアス化された式を逐語的に使用しない理由は、属性が汎用クエリ API に参加し、API のユーザーに他の属性として表示されるようにするためです。 . したがって、次のことが可能になるはずです。

class PeopleController < ApplicationController
  def search
    group_columns = params[:group].split(" ") # age_quintile could be one of
    measurements = params[:measurements].split(" ") # height could be one of
    aggregates = %w[min avg max]
    select_columns = measurement.map{|m| 
      aggregates.map{|fn| "#{fn}(#{m})"} 
    }.flatten
    render :json => Person.
                      select( group_columns + select_columns ).
                      group(group_columns).
                      search(group_columns)
  end
end

クエリ文字列?group=age_quintile&measurements=heightは次のようになります。

  SELECT (age/5) as age_quintile, min(height), avg(height), max(height)
    FROM persons 
GROUP BY (age/5) 
ORDER BY (age/5);
4

1 に答える 1