4

我追求的是虚拟属性之类的东西,但这将在数据库级别上起作用:假设我有一个字段age,我想添加一个age_quintile等于的“虚拟字段” age/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 或一些宝石来做到这一点?

更新

希望在模型中声明这些属性,而不是像建议的那样在 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

3

这是可能的。更重要的是,它是由 ActiveRecord 自动完成的:

@people = Person.
  select('(age/5) as age_quintile, height').
  group(:age_quintile).
  order(:age_quintile)
person = @people.first
person.age_quintile
# => age_quintile value (person.age / 5)
于 2013-10-11T15:06:56.120 回答