diff options
author | Nick Kallen <nkallen@nick-kallens-computer-2.local> | 2008-02-03 15:43:16 -0800 |
---|---|---|
committer | Nick Kallen <nkallen@nick-kallens-computer-2.local> | 2008-02-03 15:43:16 -0800 |
commit | 6c73e3dbc714a9752a66a6da51e7e41f372797b3 (patch) | |
tree | 55571262b97fc7a91114af78d04f231b1c3e3892 | |
parent | 9c4403f67a8f2ac40fc0c964d8c24ecc6c6d7f27 (diff) | |
download | rails-6c73e3dbc714a9752a66a6da51e7e41f372797b3.tar.gz rails-6c73e3dbc714a9752a66a6da51e7e41f372797b3.tar.bz2 rails-6c73e3dbc714a9752a66a6da51e7e41f372797b3.zip |
i know it doesn't work but need to anchor here...
26 files changed, 304 insertions, 349 deletions
diff --git a/lib/active_relation/primitives.rb b/lib/active_relation/primitives.rb index 5d35f42564..2ac157297e 100644 --- a/lib/active_relation/primitives.rb +++ b/lib/active_relation/primitives.rb @@ -1,3 +1,3 @@ require 'active_relation/primitives/attribute' -require 'active_relation/primitives/aggregation' +require 'active_relation/primitives/expression' diff --git a/lib/active_relation/primitives/aggregation.rb b/lib/active_relation/primitives/aggregation.rb deleted file mode 100644 index 51ceee6e66..0000000000 --- a/lib/active_relation/primitives/aggregation.rb +++ /dev/null @@ -1,35 +0,0 @@ -module ActiveRelation - class Aggregation - include Sql::Quoting - - attr_reader :attribute, :function_sql, :alias - delegate :relation, :to => :attribute - - def initialize(attribute, function_sql, aliaz = nil) - @attribute, @function_sql, @alias = attribute, function_sql, aliaz - end - - module Transformations - def substitute(new_relation) - Aggregation.new(attribute.substitute(new_relation), function_sql, @alias) - end - - def as(aliaz) - Aggregation.new(attribute, function_sql, aliaz) - end - - def to_attribute - Attribute.new(relation, @alias) - end - end - include Transformations - - def to_sql(strategy = nil) - "#{function_sql}(#{attribute.to_sql})" + (@alias ? " AS #{quote_column_name(@alias)}" : '') - end - - def ==(other) - self.class == other.class and attribute == other.attribute and function_sql == other.function_sql - end - end -end
\ No newline at end of file diff --git a/lib/active_relation/primitives/attribute.rb b/lib/active_relation/primitives/attribute.rb index 3b63bf985b..8d40a4141f 100644 --- a/lib/active_relation/primitives/attribute.rb +++ b/lib/active_relation/primitives/attribute.rb @@ -60,28 +60,28 @@ module ActiveRelation end include Predications - module Aggregations + module Expressions def count - Aggregation.new(self, "COUNT") + Expression.new(self, "COUNT") end def sum - Aggregation.new(self, "SUM") + Expression.new(self, "SUM") end def maximum - Aggregation.new(self, "MAX") + Expression.new(self, "MAX") end def minimum - Aggregation.new(self, "MIN") + Expression.new(self, "MIN") end def average - Aggregation.new(self, "AVG") + Expression.new(self, "AVG") end end - include Aggregations + include Expressions def to_sql(strategy = Sql::Predicate.new) strategy.attribute relation.name, name, self.alias diff --git a/lib/active_relation/relations.rb b/lib/active_relation/relations.rb index c9b9de93b2..27dd229f3f 100644 --- a/lib/active_relation/relations.rb +++ b/lib/active_relation/relations.rb @@ -2,8 +2,7 @@ require 'active_relation/relations/relation' require 'active_relation/relations/compound' require 'active_relation/relations/table' require 'active_relation/relations/join' -require 'active_relation/relations/schmoin' -require 'active_relation/relations/group' +require 'active_relation/relations/aggregation' require 'active_relation/relations/projection' require 'active_relation/relations/selection' require 'active_relation/relations/order' diff --git a/lib/active_relation/relations/aggregation.rb b/lib/active_relation/relations/aggregation.rb new file mode 100644 index 0000000000..161a748567 --- /dev/null +++ b/lib/active_relation/relations/aggregation.rb @@ -0,0 +1,27 @@ +module ActiveRelation + class Aggregation < Compound + attr_reader :expressions, :groupings + alias_method :attributes, :expressions + + def initialize(relation, options) + @relation, @expressions, @groupings = relation, options[:expressions], options[:groupings] + end + + def ==(other) + relation == other.relation and groupings == other.groupings and expressions == other.expressions + end + + def qualify + Aggregation.new(relation.qualify, :expressions => expressions.collect(&:qualify), :groupings => groupings.collect(&:qualify)) + end + + protected + def aggregation? + true + end + + def attribute_for_expression(expression) + expression.relation == self ? expression : (e = @expressions.detect { |e| e == expression }) && e.substitute(self) + end + end +end
\ No newline at end of file diff --git a/lib/active_relation/relations/alias.rb b/lib/active_relation/relations/alias.rb index 26b582e98a..5460413b25 100644 --- a/lib/active_relation/relations/alias.rb +++ b/lib/active_relation/relations/alias.rb @@ -1,25 +1,13 @@ module ActiveRelation class Alias < Compound attr_reader :alias - alias_method :name, :alias def initialize(relation, aliaz) @relation, @alias = relation, aliaz end - def attributes - relation.attributes.collect { |a| a.substitute(self) } - end - def ==(other) relation == other.relation and @alias == other.alias end - - protected - def attribute(name) - if unaliased_attribute = relation[name] - unaliased_attribute.substitute(self) - end - end end end
\ No newline at end of file diff --git a/lib/active_relation/relations/compound.rb b/lib/active_relation/relations/compound.rb index 332147523e..7c4a7e707b 100644 --- a/lib/active_relation/relations/compound.rb +++ b/lib/active_relation/relations/compound.rb @@ -1,8 +1,25 @@ module ActiveRelation class Compound < Relation attr_reader :relation - delegate :projections, :attributes, :attribute, :joins, :selects, :orders, :groupings, :table_sql, :inserts, :limit, + delegate :joins, :selects, :orders, :groupings, :table_sql, :inserts, :limit, :offset, :name, :alias, :aggregation?, :to => :relation + + def attributes + relation.attributes.collect { |a| a.substitute(self) } + end + + protected + def attribute_for_name(name) + (a = relation[name]) && a.substitute(self) + end + + def attribute_for_attribute(attribute) + attribute.relation == self ? attribute : (a = relation[attribute]) && a.substitute(self) + end + + def attribute_for_expression(expression) + expression.relation == self ? expression : (a = relation[expression]) && a.substitute(self) + end end end
\ No newline at end of file diff --git a/lib/active_relation/relations/group.rb b/lib/active_relation/relations/group.rb deleted file mode 100644 index 31de6f4bd8..0000000000 --- a/lib/active_relation/relations/group.rb +++ /dev/null @@ -1,21 +0,0 @@ -module ActiveRelation - class Group < Compound - attr_reader :groupings - - def initialize(relation, *groupings) - @relation, @groupings = relation, groupings - end - - def ==(other) - relation == other.relation and groupings == other.groupings - end - - def qualify - Group.new(relation.qualify, *groupings.collect(&:qualify)) - end - - def aggregation? - true - end - end -end
\ No newline at end of file diff --git a/lib/active_relation/relations/join.rb b/lib/active_relation/relations/join.rb index 37ed558e9f..dfc9992f0b 100644 --- a/lib/active_relation/relations/join.rb +++ b/lib/active_relation/relations/join.rb @@ -17,7 +17,10 @@ module ActiveRelation end def attributes - projections.map(&:to_attribute) + [ + relation1.aggregation?? relation1.attributes.collect(&:to_attribute) : relation1.attributes, + relation2.aggregation?? relation2.attributes.collect(&:to_attribute) : relation2.attributes, + ].flatten end protected @@ -32,16 +35,13 @@ module ActiveRelation ].compact.flatten end - def projections - [ - relation1.aggregation?? relation1.attributes : relation1.send(:projections), - relation2.aggregation?? relation2.attributes : relation2.send(:projections), - ].flatten - end - - def attribute(name) + def attribute_for_name(name) relation1[name] || relation2[name] end + + def attribute_for_attribute(attribute) + relation1[attribute] || relation2[attribute] + end def table_sql relation1.aggregation?? relation1.to_sql(Sql::Aggregation.new) : relation1.send(:table_sql) diff --git a/lib/active_relation/relations/projection.rb b/lib/active_relation/relations/projection.rb index 9651acd021..78698603f0 100644 --- a/lib/active_relation/relations/projection.rb +++ b/lib/active_relation/relations/projection.rb @@ -1,6 +1,7 @@ module ActiveRelation class Projection < Compound attr_reader :projections + alias_method :attributes, :projections def initialize(relation, *projections) @relation, @projections = relation, projections diff --git a/lib/active_relation/relations/relation.rb b/lib/active_relation/relations/relation.rb index d09ee058ef..838697a2ac 100644 --- a/lib/active_relation/relations/relation.rb +++ b/lib/active_relation/relations/relation.rb @@ -26,10 +26,14 @@ module ActiveRelation def [](index) case index - when Symbol - attribute(index) + when Symbol, String + attribute_for_name(index) when ::Range Range.new(self, index) + when Attribute + attribute_for_attribute(index) + when Expression + attribute_for_expression(index) end end @@ -65,8 +69,8 @@ module ActiveRelation Deletion.new(self) end - def group(*attributes) - Group.new(self, *attributes) + def aggregate(*expressions) + AggregateOperation.new(self, expressions) end JoinOperation = Struct.new(:join_sql, :relation1, :relation2) do @@ -74,6 +78,12 @@ 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 @@ -83,7 +93,7 @@ module ActiveRelation def to_sql(strategy = Sql::Select.new) strategy.select [ - "SELECT #{projections.collect{ |a| a.to_sql(Sql::Projection.new) }.join(', ')}", + "SELECT #{attributes.collect{ |a| a.to_sql(Sql::Projection.new) }.join(', ')}", "FROM #{table_sql}", (joins unless joins.blank?), ("WHERE #{selects.collect{|s| s.to_sql(Sql::Predicate.new)}.join("\n\tAND ")}" unless selects.blank?), @@ -99,15 +109,23 @@ module ActiveRelation def connection ActiveRecord::Base.connection end + + def attribute_for_attribute(attribute) + self == attribute.relation ? attribute : nil + end + + def attribute_for_expression(expression) + nil + end - def projections; [] end - def selects; [] end - def orders; [] end - def inserts; [] end - def groupings; [] end - def joins; nil end - def limit; nil end - def offset; nil end - def alias; nil end + def attributes; [] end + def selects; [] end + def orders; [] end + def inserts; [] end + def groupings; [] end + def joins; nil end + def limit; nil end + def offset; nil end + def alias; nil end end end
\ No newline at end of file diff --git a/lib/active_relation/relations/rename.rb b/lib/active_relation/relations/rename.rb index 94e5edcd47..8942ffbe29 100644 --- a/lib/active_relation/relations/rename.rb +++ b/lib/active_relation/relations/rename.rb @@ -1,40 +1,52 @@ module ActiveRelation class Rename < Compound - attr_reader :autonym, :pseudonym + attr_reader :attribute, :pseudonym def initialize(relation, pseudonyms) - @autonym, @pseudonym = pseudonyms.shift + @attribute, @pseudonym = pseudonyms.shift @relation = pseudonyms.empty?? relation : Rename.new(relation, pseudonyms) end def ==(other) - relation == other.relation and autonym == other.autonym and pseudonym == other.pseudonym + self.class == other.class and relation == other.relation and attribute == other.attribute and pseudonym == other.pseudonym end def qualify - Rename.new(relation.qualify, autonym.qualify => self.pseudonym) + Rename.new(relation.qualify, attribute.qualify => pseudonym) end def attributes - projections.collect(&:to_attribute) + relation.attributes.collect(&method(:substitute)) end protected - def projections - relation.send(:projections).collect(&method(:substitute)) - end - - def attribute(name) + def attribute_for_name(name) case - when name == pseudonym then autonym.as(pseudonym) - when relation[name] == autonym then nil - else relation[name] + when referring_by_autonym?(name) then nil + when referring_by_pseudonym?(name) then attribute.as(pseudonym).substitute(self) + else (a = relation[name]) && a.substitute(self) end end + + def attribute_for_attribute(attribute) + attribute.relation == self ? attribute : substitute(relation[attribute]) + end + + def attribute_for_expression(expression) + expression.relation == self ? expression : substitute(relation[expression]) + end private def substitute(attribute) - attribute == autonym ? attribute.as(pseudonym) : attribute + (relation[attribute] == relation[self.attribute] ? attribute.as(pseudonym) : attribute).substitute(self) if attribute + end + + def referring_by_autonym?(name) + relation[name] == relation[attribute] + end + + def referring_by_pseudonym?(name) + name == pseudonym end end end
\ No newline at end of file diff --git a/lib/active_relation/relations/schmoin.rb b/lib/active_relation/relations/schmoin.rb deleted file mode 100644 index 6d0cb6f171..0000000000 --- a/lib/active_relation/relations/schmoin.rb +++ /dev/null @@ -1,43 +0,0 @@ -module ActiveRelation - class Schmoin < Relation - attr_reader :join_sql, :relation1, :relation2, :predicates - delegate :table_sql, :to => :relation1 - - def initialize(join_sql, relation1, relation2, *predicates) - @join_sql, @relation1, @relation2, @predicates = join_sql, relation1, relation2, predicates - end - - def ==(other) - predicates == other.predicates and - ((relation1 == other.relation1 and relation2 == other.relation2) or - (relation2 == other.relation1 and relation1 == other.relation2)) - end - - def qualify - Schmoin.new(join_sql, relation1.qualify, relation2.qualify, *predicates.collect(&:qualify)) - end - - protected - def joins - [relation1.joins, relation2.joins, join].compact.join(" ") - end - - def selects - relation1.send(:selects) + relation2.send(:selects) - end - - # this is magick!!! - def projections - relation1.projections + relation2.attributes - end - - def attribute(name) - relation1[name] || relation2[name] - end - - private - def join - "#{join_sql} #{relation2.to_sql(Sql::Aggregation.new)} ON #{predicates.collect { |p| p.to_sql(Sql::Predicate.new) }.join(' AND ')}" - end - end -end
\ No newline at end of file diff --git a/lib/active_relation/relations/table.rb b/lib/active_relation/relations/table.rb index 637273f949..ffc9077076 100644 --- a/lib/active_relation/relations/table.rb +++ b/lib/active_relation/relations/table.rb @@ -13,14 +13,16 @@ module ActiveRelation def qualify Rename.new self, qualifications end - - protected - alias_method :projections, :attributes - def attribute(name) + def inspect + "<Table: #{name}>" + end + + protected + def attribute_for_name(name) attributes_by_name[name.to_s] end - + def table_sql "#{quote_table_name(name)}" end diff --git a/spec/active_relation/predicates/equality_spec.rb b/spec/active_relation/predicates/equality_spec.rb index d23893e438..f947bc6fe7 100644 --- a/spec/active_relation/predicates/equality_spec.rb +++ b/spec/active_relation/predicates/equality_spec.rb @@ -23,8 +23,5 @@ module ActiveRelation Equality.new(@attribute1, @attribute2).should == Equality.new(@attribute2, @attribute1) end end - - describe '#to_sql' do - end end end
\ No newline at end of file diff --git a/spec/active_relation/primitives/aggregation_spec.rb b/spec/active_relation/primitives/aggregation_spec.rb deleted file mode 100644 index 5daf774e06..0000000000 --- a/spec/active_relation/primitives/aggregation_spec.rb +++ /dev/null @@ -1,62 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper') - -module ActiveRelation - describe Aggregation do - before do - @relation1 = Table.new(:foo) - @relation2 = Table.new(:bar) - end - - describe '==' do - it 'obtains if the attribute and function sql are identical' do - Aggregation.new(@relation1[:id], "SUM").should == Aggregation.new(@relation1[:id], "SUM") - Aggregation.new(@relation1[:id], "SUM").should_not == Aggregation.new(@relation1[:name], "SUM") - Aggregation.new(@relation1[:id], "SUM").should_not == Aggregation.new(@relation1[:name], "SUM") - Aggregation.new(@relation1[:id], "SUM").should_not == Aggregation.new(@relation2[:id], "SUM") - end - end - - describe Aggregation::Transformations do - describe '#substitute' do - it "distributes over the attribute and alias" do - Aggregation.new(@relation1[:id], "SUM", "alias").substitute(@relation2). \ - should == Aggregation.new(@relation1[:id].substitute(@relation2), "SUM", "alias") - end - end - - describe '#as' do - it "manufactures an aliased aggregation" do - Aggregation.new(@relation1[:id], "SUM").as(:doof). \ - should == Aggregation.new(@relation1[:id], "SUM", :doof) - end - end - - describe '#to_attribute' do - it "manufactures an attribute the name of which corresponds to the aggregation's alias" do - Aggregation.new(@relation1[:id], "SUM", :schmaggregation).to_attribute. \ - should == Attribute.new(@relation1, :schmaggregation) - end - end - end - - describe '#relation' do - it "delegates to the attribute" do - Aggregation.new(@relation1[:id], "SUM").relation.should == @relation1 - end - end - - describe '#to_sql' do - it 'manufactures sql with an aggregation function' do - Aggregation.new(@relation1[:id], "MAX").to_sql.should be_like(""" - MAX(`foo`.`id`) - """) - end - - it 'manufactures sql with an aliased aggregation function' do - Aggregation.new(@relation1[:id], "MAX", "marx").to_sql.should be_like(""" - MAX(`foo`.`id`) AS `marx` - """) - end - end - end -end
\ No newline at end of file diff --git a/spec/active_relation/primitives/attribute_spec.rb b/spec/active_relation/primitives/attribute_spec.rb index 7f5d4922b8..f76018c493 100644 --- a/spec/active_relation/primitives/attribute_spec.rb +++ b/spec/active_relation/primitives/attribute_spec.rb @@ -41,10 +41,6 @@ module ActiveRelation it "manufactures an attribute name prefixed with the relation's name" do Attribute.new(@relation1, :id).qualified_name.should == 'foo.id' end - - it "manufactures an attribute name prefixed with the relation's aliased name" do - Attribute.new(@relation1.as(:bar), :id).qualified_name.should == 'bar.id' - end end describe '==' do @@ -52,11 +48,36 @@ module ActiveRelation Attribute.new(@relation1, :name).should == Attribute.new(@relation1, :name) Attribute.new(@relation1, :name).should_not == Attribute.new(@relation1, :another_name) Attribute.new(@relation1, :name).should_not == Attribute.new(@relation2, :name) - Attribute.new(@relation1, :name).should_not == Aggregation.new(Attribute.new(@relation1, :name), "SUM") + Attribute.new(@relation1, :name).should_not == Expression.new(Attribute.new(@relation1, :name), "SUM") + end + end + + describe '#to_sql' do + describe Sql::Strategy do + it "manufactures sql without an alias if the strategy is Predicate" do + Attribute.new(@relation1, :name, :alias).to_sql(Sql::Predicate.new).should be_like("`foo`.`name`") + end + + it "manufactures sql with an alias if the strategy is Projection" do + Attribute.new(@relation1, :name, :alias).to_sql(Sql::Projection.new).should be_like("`foo`.`name` AS 'alias'") + end + end + + describe 'binding' do + before do + @attribute = Attribute.new(@relation1, :name, :alias) + @aliased_relation = @relation1.as(:schmoo) + end + + it "is fancy pants" do + pending + @attribute.to_sql.should be_like("`foo`.`name`") + @attribute.substitute(@aliased_relation).to_sql.should be_like("`schmoo`.`alias`") + end end end - describe 'predications' do + describe Attribute::Predications do before do @attribute1 = Attribute.new(@relation1, :name) @attribute2 = Attribute.new(@relation2, :name) @@ -99,38 +120,38 @@ module ActiveRelation end end - describe 'aggregations' do + describe 'Expressions' do before do @attribute1 = Attribute.new(@relation1, :name) end describe '#count' do - it "manufactures a count aggregation" do - @attribute1.count.should == Aggregation.new(@attribute1, "COUNT") + it "manufactures a count Expression" do + @attribute1.count.should == Expression.new(@attribute1, "COUNT") end end describe '#sum' do - it "manufactures a sum aggregation" do - @attribute1.sum.should == Aggregation.new(@attribute1, "SUM") + it "manufactures a sum Expression" do + @attribute1.sum.should == Expression.new(@attribute1, "SUM") end end describe '#maximum' do - it "manufactures a maximum aggregation" do - @attribute1.maximum.should == Aggregation.new(@attribute1, "MAX") + it "manufactures a maximum Expression" do + @attribute1.maximum.should == Expression.new(@attribute1, "MAX") end end describe '#minimum' do - it "manufactures a minimum aggregation" do - @attribute1.minimum.should == Aggregation.new(@attribute1, "MIN") + it "manufactures a minimum Expression" do + @attribute1.minimum.should == Expression.new(@attribute1, "MIN") end end describe '#average' do - it "manufactures an average aggregation" do - @attribute1.average.should == Aggregation.new(@attribute1, "AVG") + it "manufactures an average Expression" do + @attribute1.average.should == Expression.new(@attribute1, "AVG") end end end diff --git a/spec/active_relation/relations/alias_spec.rb b/spec/active_relation/relations/alias_spec.rb index 6c203990eb..c02b0df453 100644 --- a/spec/active_relation/relations/alias_spec.rb +++ b/spec/active_relation/relations/alias_spec.rb @@ -6,24 +6,5 @@ module ActiveRelation @relation = Table.new(:users) @alias_relation = @relation.as(:foo) end - - describe '#name' do - it 'returns the alias' do - @alias_relation.name.should == :foo - end - end - - describe '#attributes' do - it 'manufactures sql deleting a table relation' do - @alias_relation.attributes.should == @relation.attributes.collect { |a| Attribute.new(@alias_relation, a.name) } - end - end - - describe '[]' do - it 'manufactures attributes associated with the aliased relation' do - @alias_relation[:id].relation.should == @alias_relation - @alias_relation[:does_not_exist].should be_nil - end - end end end
\ No newline at end of file diff --git a/spec/active_relation/relations/compound_spec.rb b/spec/active_relation/relations/compound_spec.rb index 6309547c7d..a03b0206a9 100644 --- a/spec/active_relation/relations/compound_spec.rb +++ b/spec/active_relation/relations/compound_spec.rb @@ -3,13 +3,50 @@ require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper') module ActiveRelation describe Compound do before do - @relation = Table.new(:users) - class ConcreteCompound < Compound def initialize(relation) @relation = relation end end + @relation = Table.new(:users) + @compound_relation = ConcreteCompound.new(@relation) + end + + describe '#attributes' do + it 'manufactures attributes associated with the compound relation' do + @compound_relation.attributes.should == @relation.attributes.collect { |a| Attribute.new(@compound_relation, a.name) } + end + end + + describe '[]' do + describe 'when given a', Symbol do + it 'manufactures attributes associated with the compound relation if the symbol names an attribute within the relation' do + @compound_relation[:id].relation.should == @compound_relation + @compound_relation[:does_not_exist].should be_nil + end + end + + describe 'when given an', Attribute do + it "manufactures a substituted attribute when given an attribute within the relation" do + @compound_relation[Attribute.new(@relation, :id)].should == Attribute.new(@compound_relation, :id) + @compound_relation[Attribute.new(@compound_relation, :id)].should == Attribute.new(@compound_relation, :id) + @compound_relation[Attribute.new(another_relation = Table.new(:photos), :id)].should be_nil + end + end + + describe 'when given an', Expression do + before do + @nested_expression = Expression.new(Attribute.new(@relation, :id), "COUNT") + @unprojected_expression = Expression.new(Attribute.new(@relation, :id), "SUM") + @compound_relation = ConcreteCompound.new(Aggregation.new(@relation, :expressions => [@nested_expression])) + end + + it "manufactures a substituted Expression when given an Expression within the relation" do + @compound_relation[@nested_expression].should == @nested_expression.substitute(@compound_relation) + @compound_relation[@compound_relation[@expression]].should == @compound_relation[@expression] + @compound_relation[@unprojected_expression].should be_nil + end + end end end end
\ No newline at end of file diff --git a/spec/active_relation/relations/group_spec.rb b/spec/active_relation/relations/group_spec.rb deleted file mode 100644 index 532d6faea6..0000000000 --- a/spec/active_relation/relations/group_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper') - -module ActiveRelation - describe Group do - before do - @relation1 = Table.new(:foo) - @relation2 = Table.new(:bar) - @attribute1 = @relation1[:id] - @attribute2 = @relation2[:id] - end - - describe '#qualify' do - it "distributes over the relation and attributes" do - Group.new(@relation1, @attribute1).qualify. \ - should == Group.new(@relation1.qualify, @attribute1.qualify) - end - end - - describe '#aggregation?' do - it "is true" do - Group.new(@relation1, @attribute1).should be_aggregation - end - end - - describe '#to_sql' do - it "manufactures sql with an order clause" do - Group.new(@relation1, @attribute1).to_sql.should be_like(""" - SELECT `foo`.`name`, `foo`.`id` - FROM `foo` - GROUP BY `foo`.`id` - """) - end - end - end -end diff --git a/spec/active_relation/relations/join_spec.rb b/spec/active_relation/relations/join_spec.rb index 0f30d11f98..5235a5b528 100644 --- a/spec/active_relation/relations/join_spec.rb +++ b/spec/active_relation/relations/join_spec.rb @@ -18,6 +18,12 @@ module ActiveRelation Join.new("INNER JOIN", @relation1, @relation2, @predicate).should == Join.new("INNER JOIN", @relation2, @relation1, @predicate) end end + + describe '[]' do + it "" do + pending + end + end describe '#qualify' do it 'distributes over the relations and predicates' do @@ -63,17 +69,16 @@ module ActiveRelation end end - describe 'aggregated relations' do before do @relation = Table.new(:users) photos = Table.new(:photos) - @aggregate_relation = photos.project(photos[:user_id], photos[:id].count).rename(photos[:id].count, :cnt) \ - .group(photos[:user_id]).as(:photo_count) + @aggregate_relation = photos.aggregate(photos[:user_id], photos[:id].count).group(photos[:user_id]).rename(photos[:id].count, :cnt) \ + .as(:photo_count) @predicate = Equality.new(@aggregate_relation[:user_id], @relation[:id]) end - describe 'with the aggregation on the right' do + describe 'with the expression on the right' do it 'manufactures sql joining the left table to a derived table' do Join.new("INNER JOIN", @relation, @aggregate_relation, @predicate).to_sql.should be_like(""" SELECT `users`.`name`, `users`.`id`, `photo_count`.`user_id`, `photo_count`.`cnt` @@ -84,9 +89,8 @@ module ActiveRelation end end - describe 'with the aggregation on the left' do + describe 'with the expression on the left' do it 'manufactures sql joining the right table to a derived table' do - pending Join.new("INNER JOIN", @aggregate_relation, @relation, @predicate).to_sql.should be_like(""" SELECT `photo_count`.`user_id`, `photo_count`.`cnt`, `users`.`name`, `users`.`id` FROM (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photo_count` @@ -96,7 +100,7 @@ module ActiveRelation end end - it "keeps selects on the aggregation within the derived table" do + it "keeps selects on the expression within the derived table" do pending Join.new("INNER JOIN", @relation, @aggregate_relation.select(@aggregate_relation[:user_id].equals(1)), @predicate).to_sql.should be_like(""" SELECT `users`.`name`, `users`.`id`, `photo_count`.`user_id`, `photo_count`.`cnt` diff --git a/spec/active_relation/relations/projection_spec.rb b/spec/active_relation/relations/projection_spec.rb index 8d6a093af2..e792eec3b8 100644 --- a/spec/active_relation/relations/projection_spec.rb +++ b/spec/active_relation/relations/projection_spec.rb @@ -9,6 +9,10 @@ module ActiveRelation @attribute2 = @relation2[:id] end + it "needs to test that [] is limited" do + pending + end + describe '==' do it "obtains if the relations and attributes are identical" do Projection.new(@relation1, @attribute1, @attribute2).should == Projection.new(@relation1, @attribute1, @attribute2) diff --git a/spec/active_relation/relations/relation_spec.rb b/spec/active_relation/relations/relation_spec.rb index 05330206e0..e28487b373 100644 --- a/spec/active_relation/relations/relation_spec.rb +++ b/spec/active_relation/relations/relation_spec.rb @@ -10,10 +10,6 @@ module ActiveRelation end describe '[]' do - it "manufactures an attribute when given a symbol" do - @relation1[:id].should == Attribute.new(@relation1, :id) - end - it "manufactures a range relation when given a range" do @relation1[1..2].should == Range.new(@relation1, 1..2) end @@ -25,7 +21,7 @@ module ActiveRelation end end - describe '#aggregation?' do + describe '#Expression?' do it "returns false" do @relation1.should_not be_aggregation end @@ -88,9 +84,10 @@ module ActiveRelation end end - describe '#group' do + describe '#aggregate' do it 'manufactures a group relation' do - @relation1.group(@attribute1).should == Group.new(@relation1, @attribute1) + @relation1.aggregate(@expression1, @expression2).group(@attribute1, @attribute2). \ + should == Aggregation.new(@relation1, :expressions => [@expresion, @expression2], :groupings => [@attribute1, @attribute2]) end end end diff --git a/spec/active_relation/relations/rename_spec.rb b/spec/active_relation/relations/rename_spec.rb index 1616d5fdb7..65ad9c51bd 100644 --- a/spec/active_relation/relations/rename_spec.rb +++ b/spec/active_relation/relations/rename_spec.rb @@ -25,15 +25,61 @@ module ActiveRelation describe '#attributes' do it "manufactures a list of attributes with the renamed attribute renameed" do - Rename.new(@relation1, @relation1[:id] => :schmid).attributes.should == - (@relation1.attributes - [@relation1[:id]]) + [@relation1[:id].as(:schmid)] + @renamed_relation.attributes.should include(Attribute.new(@renamed_relation, :id, :schmid)) + @renamed_relation.should have(@relation1.attributes.size).attributes end end describe '[]' do - it 'indexes attributes by rename' do - @renamed_relation[:id].should be_nil - @renamed_relation[:schmid].should == @relation1[:id].as(:schmid) + describe 'when given a', Symbol do + it 'indexes attributes by rename if the symbol names an attribute within the relation' do + @renamed_relation[:id].should be_nil + @renamed_relation[:schmid].should == Attribute.new(@renamed_relation, :id, :schmid) + @renamed_relation[:does_not_exist].should be_nil + end + end + + describe 'when given an', Attribute do + it 'manufactures a substituted and renamed attribute if the attribute is within the relation' do + @renamed_relation[Attribute.new(@relation1, :id)].should == Attribute.new(@renamed_relation, :id, :schmid) + @renamed_relation[Attribute.new(@relation1, :name)].should == Attribute.new(@renamed_relation, :name) + @renamed_relation[Attribute.new(@renamed_relation, :name)].should == Attribute.new(@renamed_relation, :name) + @renamed_relation[Attribute.new(@relation2, :id)].should be_nil + end + end + + describe 'when given an', Expression do + it "manufactures a substituted and renamed expression if the expression is within the relation" do + end + end + + describe 'when the rename is constructed with a derived attribute' do + before do + @renamed_renamed_relation = Rename.new(@renamed_relation, @relation1[:id] => :flid) + end + + describe 'when given a', Symbol do + it 'manufactures a substituted and renamed attribute if the attribute is within the relation' do + @renamed_renamed_relation[:id].should be_nil + @renamed_renamed_relation[:schmid].should be_nil + @renamed_renamed_relation[:flid].should == Attribute.new(@renamed_renamed_relation, :id, :flid) + end + end + + describe 'when given an', Attribute do + it "manufactures a substituted and renamed attribute if the attribute is within the relation -- even if the provided attribute derived" do + @renamed_renamed_relation[Attribute.new(@renamed_relation, :id, :schmid)].should == Attribute.new(@renamed_renamed_relation, :id, :flid) + @renamed_renamed_relation[Attribute.new(@relation1, :id)].should == Attribute.new(@renamed_renamed_relation, :id, :flid) + end + end + + describe 'when given an', Expression do + it "manufactures a substituted and renamed expression if the expression is within the relation" do + renamed_relation = Rename.new(Aggregation.new(@relation1, :expressions => [@relation1[:id].count]), @relation1[:id].count => :cnt) + renamed_relation[@relation1[:id].count].should == @relation1[:id].count.as(:cnt).substitute(renamed_relation) + renamed_relation.attributes.should == [@relation1[:id].count.as(:cnt).substitute(renamed_relation)] + end + end end end @@ -45,7 +91,7 @@ module ActiveRelation end describe '#to_sql' do - it 'manufactures sql renameing the attribute' do + it 'manufactures sql renaming the attribute' do @renamed_relation.to_sql.should be_like(""" SELECT `foo`.`name`, `foo`.`id` AS 'schmid' FROM `foo` diff --git a/spec/active_relation/relations/schmoin_spec.rb b/spec/active_relation/relations/schmoin_spec.rb deleted file mode 100644 index e5ed9be393..0000000000 --- a/spec/active_relation/relations/schmoin_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper') - -module ActiveRelation - describe Schmoin do - before do - @relation = Table.new(:users) - photos = Table.new(:photos) - @aggregate_relation = photos.project(photos[:user_id], photos[:id].count).rename(photos[:id].count, :cnt) \ - .group(photos[:user_id]).as(:photo_count) - @predicate = Equality.new(@aggregate_relation[:user_id], @relation[:id]) - end - - describe '#to_sql' do - it 'manufactures sql joining the two tables on the predicate, merging the selects' do - Schmoin.new("INNER JOIN", @relation, @aggregate_relation, @predicate).to_sql.should be_like(""" - SELECT `users`.`name`, `users`.`id`, `photo_count`.`user_id`, `photo_count`.`cnt` - FROM `users` - INNER JOIN (SELECT `photos`.`user_id`, COUNT(`photos`.`id`) AS `cnt` FROM `photos` GROUP BY `photos`.`user_id`) AS `photo_count` - ON `photo_count`.`user_id` = `users`.`id` - """) - end - end - end -end
\ No newline at end of file diff --git a/spec/active_relation/relations/table_spec.rb b/spec/active_relation/relations/table_spec.rb index c8679707f5..140346e6f6 100644 --- a/spec/active_relation/relations/table_spec.rb +++ b/spec/active_relation/relations/table_spec.rb @@ -6,6 +6,32 @@ module ActiveRelation @relation = Table.new(:users) end + describe '[]' do + describe 'when given a', Symbol do + it "manufactures an attribute if the symbol names an attribute within the relation" do + @relation[:id].should == Attribute.new(@relation, :id) + @relation[:does_not_exist].should be_nil + end + end + + describe 'when given an', Attribute do + it "returns the attribute if the attribute is within the relation" do + @relation[Attribute.new(@relation, :id)].should == Attribute.new(@relation, :id) + @relation[Attribute.new(another_relation = Table.new(:photos), :id)].should be_nil + end + end + + describe 'when given an', Expression do + before do + @expression = Expression.new(Attribute.new(@relation, :id), "COUNT") + end + + it "returns the Expression if the Expression is within the relation" do + @relation[@expression].should be_nil + end + end + end + describe '#to_sql' do it "manufactures a simple select query" do @relation.to_sql.should be_like(""" @@ -26,9 +52,7 @@ module ActiveRelation describe '#qualify' do it 'manufactures a rename relation with all attribute names qualified' do - @relation.qualify.should == Rename.new( - Rename.new(@relation, @relation[:id] => 'users.id'), @relation[:name] => 'users.name' - ) + @relation.qualify.should == Rename.new(@relation, @relation[:id] => 'users.id', @relation[:name] => 'users.name') end end end |