1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

new conception of grouping and aggregation functionality

This commit is contained in:
Nick Kallen 2008-04-13 18:45:20 -07:00
parent 4466409205
commit 04c8e48311
11 changed files with 95 additions and 53 deletions

View file

@ -10,6 +10,10 @@ module ActiveRelation
def alias_or_name
@alias || name
end
def aggregation?
false
end
module Transformations
def as(aliaz = nil)
@ -56,10 +60,8 @@ module ActiveRelation
end
def %(other)
if other
(history - other.history) + (other.history - history)
else
history
if other then (history - other.history) + (other.history - history)
else history
end
end
end

View file

@ -29,6 +29,10 @@ module ActiveRelation
"#{function_sql}(#{attribute.to_sql})" + (@alias ? " AS #{quote_column_name(@alias)}" : '')
end
def aggregation?
true
end
def ==(other)
self.class == other.class and
attribute == other.attribute and

View file

@ -4,7 +4,7 @@ require 'active_relation/relations/compound'
require 'active_relation/relations/writing'
require 'active_relation/relations/table'
require 'active_relation/relations/join'
require 'active_relation/relations/aggregation'
require 'active_relation/relations/grouping'
require 'active_relation/relations/projection'
require 'active_relation/relations/selection'
require 'active_relation/relations/order'

View file

@ -1,24 +0,0 @@
module ActiveRelation
class Aggregation < Compound
attr_reader :expressions, :groupings
def initialize(relation, options)
@relation, @expressions, @groupings = relation, options[:expressions], options[:groupings]
end
def ==(other)
self.class == other.class and
relation == other.relation and
groupings == other.groupings and
expressions == other.expressions
end
def attributes
expressions.collect { |e| e.bind(self) }
end
def aggregation?
true
end
end
end

View file

@ -0,0 +1,19 @@
module ActiveRelation
class Grouping < Compound
attr_reader :expressions, :groupings
def initialize(relation, *groupings)
@relation, @groupings = relation, groupings.collect { |g| g.bind(relation) }
end
def ==(other)
self.class == other.class and
relation == other.relation and
groupings == other.groupings
end
def aggregation?
true
end
end
end

View file

@ -15,5 +15,9 @@ module ActiveRelation
relation == other.relation and
projections == other.projections
end
def aggregation?
attributes.any?(&:aggregation?)
end
end
end

View file

@ -66,8 +66,8 @@ module ActiveRelation
skipped.blank?? self : Skip.new(self, skipped)
end
def aggregate(*expressions)
AggregateOperation.new(self, expressions)
def group(*groupings)
groupings.all?(&:blank?) ? self : Grouping.new(self, *groupings)
end
module Writes
@ -90,12 +90,6 @@ module ActiveRelation
Join.new(join_sql, relation1, relation2, *predicates)
end
end
AggregateOperation = Struct.new(:relation, :expressions) do
def group(*groupings)
Aggregation.new(relation, :expressions => expressions, :groupings => groupings)
end
end
end
include Operations

View file

@ -0,0 +1,33 @@
require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
module ActiveRelation
describe Grouping do
before do
@relation = Table.new(:users)
@attribute = @relation[:id]
end
describe '#to_sql' do
describe 'when given a predicate' do
it "manufactures sql with where clause conditions" do
Grouping.new(@relation, @attribute).to_sql.should be_like("
SELECT `users`.`id`, `users`.`name`
FROM `users`
GROUP BY `users`.`id`
")
end
end
describe 'when given a string' do
it "passes the string through to the where clause" do
pending 'it should not quote asdf'
Grouping.new(@relation, 'asdf').to_sql.should be_like("
SELECT `users`.`id`, `users`.`name`
FROM `users`
GROUP BY asdf
")
end
end
end
end
end

View file

@ -97,8 +97,8 @@ module ActiveRelation
describe 'when joining aggregated relations' do
before do
@aggregation = @relation2 \
.aggregate(@relation2[:user_id], @relation2[:id].count.as(:cnt)) \
.group(@relation2[:user_id]) \
.project(@relation2[:user_id], @relation2[:id].count.as(:cnt)) \
.as('photo_count')
end

View file

@ -53,16 +53,29 @@ module ActiveRelation
end
describe 'when given a string' do
before do
@string = "asdf"
end
it "passes the string through to the select clause" do
Projection.new(@relation, @string).to_sql.should be_like("
Projection.new(@relation, 'asdf').to_sql.should be_like("
SELECT asdf FROM `users`
")
end
end
end
describe Projection::Externalizable do
describe '#aggregation?' do
describe 'when the projections are attributes' do
it 'returns false' do
Projection.new(@relation, @attribute).should_not be_aggregation
end
end
describe 'when the projections include an aggregation' do
it "obtains" do
Projection.new(@relation, @attribute.sum).should be_aggregation
end
end
end
end
end
end

View file

@ -154,18 +154,15 @@ module ActiveRelation
end
end
describe '#aggregate' do
before do
@expression1 = @attribute1.sum
@expression2 = @attribute2.sum
describe '#group' do
it 'manufactures a group relation' do
@relation.group(@attribute1, @attribute2).should == Grouping.new(@relation, @attribute1, @attribute2)
end
it 'manufactures a group relation' do
@relation.aggregate(@expression1, @expression2).group(@attribute1, @attribute2). \
should == Aggregation.new(@relation,
:expressions => [@expression1, @expression2],
:groupings => [@attribute1, @attribute2]
)
describe 'when given blank groupings' do
it 'returns self' do
@relation.group.should == @relation
end
end
end