Rails 的 select 方法
还是这段代码
@stats = ParticipantStat.where(round: @rounds, round_stat: %w(win draw loss)).group('participant_id')
.select(
<<-EOT
participant_id,
COUNT(round_id) as round_count,
SUM(CASE WHEN round_stat IN (1) THEN 1 ELSE 0 END) as winning_round_count,
SUM(CASE WHEN mvp THEN 1 ELSE 0 END) as total_mvp,
SUM(point) AS total_point,
SUM(rebound) AS total_rebound,
SUM(assist) AS total_assist,
SUM(score) AS total_score
EOT
).order('total_score desc, total_point desc, total_rebound desc, total_assist desc, total_mvp desc').includes(participant: :profile)
这里的用了select
方法。按照 API 的介绍,这个 select
方法后面可以有两种用法,一种是带一个匿名函数,例如
Model.all.select { |m| m.field == value }
这样的用法,得到是一个数组,而不是一个 relation object,不可以再带方法链。
另一种方法就是当做 SQL 的 SELECT 来用,这样得到的是一个 relation object,后面可以继续带方法链。比如
Model.select(:field, :other_field, :and_one_more)
这样得到的 Model
的对象会只带有三个属性,其他没有被选出来的属性无法调用,比如
Model.select(:field).first.other_field
# => ActiveModel::MissingAttributeError: missing attribute: other_field
如果不用 symbol,而是用字符串,这些字符串就会原封不动地转换成 SELECT
语句进行 SQL 查询
Model.select('field AS field_one', 'other_field AS field_two')
也就是说,字符串需要符合 SQL 语法。
读到这里,前面的代码就能看懂了,里面用到 SQL 语句有
COUNT(...) AS XXX
SUM(...) AS XXX
SUM(CASE WHEN XXX THEN XXX ELSE XXX END) AS XXX
AS
后面的可以看做是一个虚拟属性,这样就可以根据需要定制出不用条件下的属性。