woshidan's loose leaf

ぼんやり勉強しています

ActiveRecordでgroupingに計算値を使いたい、計算値を集計したい場合

.group(Arel.sql('DATE_FORMAT(updated_at, '%Y-%m-%d')'))

とか

.sum(Arel.sql("price * #{CONSUMPTION_TAX_RATE}"))

のようにArel.sql()で包んでから放り込む。 と思っていたけど、包まなくても割といけたぞ。何故だ!

Book.group('DATE_FORMAT(updated_at, "%Y-%m-%d")').to_sql
=> "SELECT `books`.* FROM `books`  GROUP BY DATE_FORMAT(updated_at, \"%Y-%m-%d\")"
Book.group(Arel.sql('DATE_FORMAT(updated_at, "%Y-%m-%d")')).to_sql
=> "SELECT `books`.* FROM `books`  GROUP BY DATE_FORMAT(updated_at, \"%Y-%m-%d\")"

コード見てても理由がよく分からなかったけど、group句とか呼んだときに、 Arel::SelectManagerで列名が自動的にArel.sqlに代入されたときと同じ処理がなされるからっぽい。

明日直そう。

https://groups.google.com/forum/#!topic/rubyonrails-core/UGZmPT1nDX4

https://github.com/rails/arel/blob/master/lib/arel/select_manager.rb

gems/arel-2.2.1/lib/arel/select_manager.rb
   def group *columns
     columns.each do |column|
       # FIXME: backwards compat
       column = Nodes::SqlLiteral.new(column) if String === column
       column = Nodes::SqlLiteral.new(column.to_s) if Symbol === column
module Arel
  VERSION = '7.0.0.alpha'

  def self.sql raw_sql
    Arel::Nodes::SqlLiteral.new raw_sql
  end

  def self.star
    sql '*'
  end
  ## Convenience Alias
  Node = Arel::Nodes::Node
end