From a83efc5d5d94d50589a80bdd27ddf5b83ed39810 Mon Sep 17 00:00:00 2001 From: Nick Kallen Date: Sat, 12 Jan 2008 20:18:52 -0800 Subject: [PATCH] added aggregations --- lib/active_relation.rb | 3 +- lib/active_relation/primitives.rb | 3 ++ lib/active_relation/primitives/aggregation.rb | 21 +++++++++ .../{relations => primitives}/attribute.rb | 43 +++++++++++++++---- lib/active_relation/relations.rb | 1 - lib/active_relation/relations/table.rb | 2 +- .../relations/attribute_spec.rb | 40 ++++++++++++++++- 7 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 lib/active_relation/primitives.rb create mode 100644 lib/active_relation/primitives/aggregation.rb rename lib/active_relation/{relations => primitives}/attribute.rb (55%) diff --git a/lib/active_relation.rb b/lib/active_relation.rb index cdac17facb..0b55ed74d0 100644 --- a/lib/active_relation.rb +++ b/lib/active_relation.rb @@ -6,5 +6,6 @@ require 'activerecord' require 'active_relation/sql_builder' require 'active_relation/extensions' +require 'active_relation/predicates' require 'active_relation/relations' -require 'active_relation/predicates' \ No newline at end of file +require 'active_relation/primitives' \ No newline at end of file diff --git a/lib/active_relation/primitives.rb b/lib/active_relation/primitives.rb new file mode 100644 index 0000000000..5d35f42564 --- /dev/null +++ b/lib/active_relation/primitives.rb @@ -0,0 +1,3 @@ +require 'active_relation/primitives/attribute' +require 'active_relation/primitives/aggregation' + diff --git a/lib/active_relation/primitives/aggregation.rb b/lib/active_relation/primitives/aggregation.rb new file mode 100644 index 0000000000..20fdcf46c5 --- /dev/null +++ b/lib/active_relation/primitives/aggregation.rb @@ -0,0 +1,21 @@ +module ActiveRelation + module Primitives + class Aggregation + include SqlBuilder + + attr_reader :attribute, :function_sql + + def initialize(attribute, function_sql) + @attribute, @function_sql = attribute, function_sql + end + + def to_sql(options = {}) + "#{function_sql}(@attribute.to_sql)" + end + + def ==(other) + self.class == other.class and attribute == other.attribute and function_sql == other.function_sql + end + end + end +end \ No newline at end of file diff --git a/lib/active_relation/relations/attribute.rb b/lib/active_relation/primitives/attribute.rb similarity index 55% rename from lib/active_relation/relations/attribute.rb rename to lib/active_relation/primitives/attribute.rb index 2fe702cb14..65ae12cf36 100644 --- a/lib/active_relation/relations/attribute.rb +++ b/lib/active_relation/primitives/attribute.rb @@ -1,7 +1,7 @@ module ActiveRelation module Primitives class Attribute - include ::ActiveRelation::SqlBuilder + include SqlBuilder attr_reader :relation, :name, :alias @@ -10,7 +10,7 @@ module ActiveRelation end def alias(aliaz = nil) - aliaz ? ActiveRelation::Primitives::Attribute.new(relation, name, aliaz) : @alias + aliaz ? Attribute.new(relation, name, aliaz) : @alias end def qualified_name @@ -25,32 +25,57 @@ module ActiveRelation relation == other.relation and name == other.name and @alias == other.alias end - module Predications + module Predications + include Predicates + def equals(other) - Predicates::Equality.new(self, other) + Equality.new(self, other) end def less_than(other) - Predicates::LessThan.new(self, other) + LessThan.new(self, other) end def less_than_or_equal_to(other) - Predicates::LessThanOrEqualTo.new(self, other) + LessThanOrEqualTo.new(self, other) end def greater_than(other) - Predicates::GreaterThan.new(self, other) + GreaterThan.new(self, other) end def greater_than_or_equal_to(other) - Predicates::GreaterThanOrEqualTo.new(self, other) + GreaterThanOrEqualTo.new(self, other) end def matches(regexp) - Predicates::Match.new(self, regexp) + Match.new(self, regexp) end end include Predications + + module Aggregations + def count + Aggregation.new(self, "COUNT") + end + + def sum + Aggregation.new(self, "SUM") + end + + def maximum + Aggregation.new(self, "MAX") + end + + def minimum + Aggregation.new(self, "MIN") + end + + def average + Aggregation.new(self, "AVG") + end + end + include Aggregations def to_sql(options = {}) "#{quote_table_name(relation.table)}.#{quote_column_name(name)}" + (options[:use_alias] && self.alias ? " AS #{self.alias.to_s.to_sql}" : "") diff --git a/lib/active_relation/relations.rb b/lib/active_relation/relations.rb index f7d1bc207a..a25e82f607 100644 --- a/lib/active_relation/relations.rb +++ b/lib/active_relation/relations.rb @@ -2,7 +2,6 @@ require 'active_relation/relations/base' require 'active_relation/relations/compound' require 'active_relation/relations/table' require 'active_relation/relations/join' -require 'active_relation/relations/attribute' require 'active_relation/relations/projection' require 'active_relation/relations/selection' require 'active_relation/relations/order' diff --git a/lib/active_relation/relations/table.rb b/lib/active_relation/relations/table.rb index 38f540cc52..d642851687 100644 --- a/lib/active_relation/relations/table.rb +++ b/lib/active_relation/relations/table.rb @@ -23,7 +23,7 @@ module ActiveRelation private def attributes_by_name @attributes_by_name ||= connection.columns(table, "#{table} Columns").inject({}) do |attributes_by_name, column| - attributes_by_name.merge(column.name => ActiveRelation::Primitives::Attribute.new(self, column.name.to_sym)) + attributes_by_name.merge(column.name => Primitives::Attribute.new(self, column.name.to_sym)) end end diff --git a/spec/active_relation/relations/attribute_spec.rb b/spec/active_relation/relations/attribute_spec.rb index 28fb0c3754..2a6deca22a 100644 --- a/spec/active_relation/relations/attribute_spec.rb +++ b/spec/active_relation/relations/attribute_spec.rb @@ -56,7 +56,7 @@ describe ActiveRelation::Primitives::Attribute do end end - describe 'greater_than' do + describe '#greater_than' do it "manufactures a greater-than predicate" do @attribute1.greater_than(@attribute2).should == ActiveRelation::Predicates::GreaterThan.new(@attribute1, @attribute2) end @@ -74,4 +74,42 @@ describe ActiveRelation::Primitives::Attribute do end end end + + describe 'aggregations' do + before do + @attribute1 = ActiveRelation::Primitives::Attribute.new(@relation1, :name) + end + + describe '#count' do + it "manufactures a count aggregation" do + @attribute1.count.should == ActiveRelation::Primitives::Aggregation.new(@attribute1, "COUNT") + end + end + + describe '#sum' do + it "manufactures a sum aggregation" do + @attribute1.sum.should == ActiveRelation::Primitives::Aggregation.new(@attribute1, "SUM") + end + end + + describe '#maximum' do + it "manufactures a maximum aggregation" do + @attribute1.maximum.should == ActiveRelation::Primitives::Aggregation.new(@attribute1, "MAX") + end + end + + describe '#minimum' do + it "manufactures a minimum aggregation" do + @attribute1.minimum.should == ActiveRelation::Primitives::Aggregation.new(@attribute1, "MIN") + end + end + + describe '#average' do + it "manufactures an average aggregation" do + @attribute1.average.should == ActiveRelation::Primitives::Aggregation.new(@attribute1, "AVG") + end + end + + + end end