diff --git a/lib/arel/attributes/attribute.rb b/lib/arel/attributes/attribute.rb index bb85af4634..bd47aa12fd 100644 --- a/lib/arel/attributes/attribute.rb +++ b/lib/arel/attributes/attribute.rb @@ -20,6 +20,10 @@ module Arel def maximum Nodes::Max.new [self], Nodes::SqlLiteral.new('max_id') end + + def average + Nodes::Avg.new [self], Nodes::SqlLiteral.new('avg_id') + end end class String < Attribute; end diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb index 4c24acb16a..8e11760c18 100644 --- a/lib/arel/nodes.rb +++ b/lib/arel/nodes.rb @@ -4,9 +4,11 @@ require 'arel/nodes/or' require 'arel/nodes/and' require 'arel/nodes/in' +require 'arel/nodes/function' require 'arel/nodes/count' require 'arel/nodes/sum' require 'arel/nodes/max' +require 'arel/nodes/avg' require 'arel/nodes/having' require 'arel/nodes/sql_literal' require 'arel/nodes/select_core' diff --git a/lib/arel/nodes/avg.rb b/lib/arel/nodes/avg.rb new file mode 100644 index 0000000000..8fc86fc21e --- /dev/null +++ b/lib/arel/nodes/avg.rb @@ -0,0 +1,6 @@ +module Arel + module Nodes + class Avg < Arel::Nodes::Function + end + end +end diff --git a/lib/arel/nodes/count.rb b/lib/arel/nodes/count.rb index 1222a791bb..2f220dbfc8 100644 --- a/lib/arel/nodes/count.rb +++ b/lib/arel/nodes/count.rb @@ -1,22 +1,11 @@ module Arel module Nodes - class Count - attr_accessor :expressions, :distinct, :alias + class Count < Arel::Nodes::Function + attr_accessor :distinct - def initialize expr, distinct = false - @expressions = expr - @distinct = distinct - @alias = nil - end - - def as aliaz - self.alias = SqlLiteral.new(aliaz) - self - end - - def to_sql - viz = Visitors::ToSql.new Table.engine - viz.accept self + def initialize expr, distinct = false, aliaz = nil + super(expr, aliaz) + @distinct = distinct end end end diff --git a/lib/arel/nodes/function.rb b/lib/arel/nodes/function.rb new file mode 100644 index 0000000000..90c6ba23a2 --- /dev/null +++ b/lib/arel/nodes/function.rb @@ -0,0 +1,22 @@ +module Arel + module Nodes + class Function + attr_accessor :expressions, :alias + + def initialize expr, aliaz = nil + @expressions = expr + @alias = aliaz + end + + def as aliaz + self.alias = SqlLiteral.new(aliaz) + self + end + + def to_sql + viz = Visitors::ToSql.new Table.engine + viz.accept self + end + end + end +end diff --git a/lib/arel/nodes/max.rb b/lib/arel/nodes/max.rb index 1766c56058..5af611b0d6 100644 --- a/lib/arel/nodes/max.rb +++ b/lib/arel/nodes/max.rb @@ -1,22 +1,6 @@ module Arel module Nodes - class Max - attr_accessor :expressions, :alias - - def initialize expr, aliaz = nil - @expressions = expr - @alias = aliaz - end - - def as aliaz - self.alias = SqlLiteral.new(aliaz) - self - end - - def to_sql - viz = Visitors::ToSql.new Table.engine - viz.accept self - end + class Max < Arel::Nodes::Function end end end diff --git a/lib/arel/nodes/sum.rb b/lib/arel/nodes/sum.rb index d81455fa5f..3e043b7330 100644 --- a/lib/arel/nodes/sum.rb +++ b/lib/arel/nodes/sum.rb @@ -1,22 +1,6 @@ module Arel module Nodes - class Sum - attr_accessor :expressions, :alias - - def initialize expr, aliaz = nil - @expressions = expr - @alias = aliaz - end - - def as aliaz - self.alias = SqlLiteral.new(aliaz) - self - end - - def to_sql - viz = Visitors::ToSql.new Table.engine - viz.accept self - end + class Sum < Arel::Nodes::Function end end end diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index 48c8c492e0..60f30967cf 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -86,6 +86,11 @@ module Arel visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}" end + def visit_Arel_Nodes_Avg o + "AVG(#{o.expressions.map { |x| + visit x }.join(', ')})#{o.alias ? " AS #{visit o.alias}" : ''}" + end + def visit_Arel_Nodes_TableAlias o "#{visit o.relation} #{quote_table_name o.name}" end diff --git a/spec/arel/attributes/attribute_spec.rb b/spec/arel/attributes/attribute_spec.rb index 449cc38dad..fb6954dc7e 100644 --- a/spec/arel/attributes/attribute_spec.rb +++ b/spec/arel/attributes/attribute_spec.rb @@ -3,6 +3,23 @@ require 'spec_helper' module Arel module Attributes describe 'attribute' do + describe '#average' do + it 'should create a AVG node' do + relation = Table.new(:users) + relation[:id].average.should be_kind_of Nodes::Avg + end + + # FIXME: backwards compat. Is this really necessary? + it 'should set the alias to "avg_id"' do + relation = Table.new(:users) + mgr = relation.project relation[:id].average + mgr.to_sql.should be_like %{ + SELECT AVG("users"."id") AS avg_id + FROM "users" + } + end + end + describe '#maximum' do it 'should create a MAX node' do relation = Table.new(:users)