diff options
-rw-r--r-- | lib/active_relation/primitives/attribute.rb | 6 | ||||
-rw-r--r-- | lib/active_relation/relations.rb | 3 | ||||
-rw-r--r-- | lib/active_relation/relations/alias.rb | 19 | ||||
-rw-r--r-- | lib/active_relation/relations/base.rb | 10 | ||||
-rw-r--r-- | lib/active_relation/relations/compound.rb | 2 | ||||
-rw-r--r-- | lib/active_relation/relations/rename.rb | 4 | ||||
-rw-r--r-- | spec/active_relation/predicates/binary_spec.rb | 10 | ||||
-rw-r--r-- | spec/active_relation/primitives/aggregation_spec.rb | 25 | ||||
-rw-r--r-- | spec/active_relation/primitives/attribute_spec.rb | 115 | ||||
-rw-r--r-- | spec/active_relation/relations/base_spec.rb | 22 | ||||
-rw-r--r-- | spec/active_relation/relations/compound_spec.rb | 13 | ||||
-rw-r--r-- | spec/active_relation/relations/projection_spec.rb | 2 | ||||
-rw-r--r-- | spec/active_relation/relations/rename_spec.rb | 4 |
13 files changed, 214 insertions, 21 deletions
diff --git a/lib/active_relation/primitives/attribute.rb b/lib/active_relation/primitives/attribute.rb index 65ae12cf36..b13f9befe1 100644 --- a/lib/active_relation/primitives/attribute.rb +++ b/lib/active_relation/primitives/attribute.rb @@ -9,8 +9,8 @@ module ActiveRelation @relation, @name, @alias = relation, name, aliaz end - def alias(aliaz = nil) - aliaz ? Attribute.new(relation, name, aliaz) : @alias + def as(aliaz = nil) + Attribute.new(relation, name, aliaz) end def qualified_name @@ -18,7 +18,7 @@ module ActiveRelation end def qualify - self.alias(qualified_name) + self.as(qualified_name) end def ==(other) diff --git a/lib/active_relation/relations.rb b/lib/active_relation/relations.rb index a25e82f607..1eb58d3b42 100644 --- a/lib/active_relation/relations.rb +++ b/lib/active_relation/relations.rb @@ -8,4 +8,5 @@ require 'active_relation/relations/order' require 'active_relation/relations/range' require 'active_relation/relations/rename' require 'active_relation/relations/deletion' -require 'active_relation/relations/insertion'
\ No newline at end of file +require 'active_relation/relations/insertion' +require 'active_relation/relations/alias'
\ No newline at end of file diff --git a/lib/active_relation/relations/alias.rb b/lib/active_relation/relations/alias.rb new file mode 100644 index 0000000000..97950ea5b3 --- /dev/null +++ b/lib/active_relation/relations/alias.rb @@ -0,0 +1,19 @@ +module ActiveRelation + module Relations + class Alias < Compound + attr_reader :alias + + def initialize(relation, aliaz) + @relation, @alias = relation, aliaz + end + + def ==(other) + relation == other.relation and self.alias == other.alias + end + + def to_sql(options = {}) + super + " AS #{@alias}" + end + end + end +end
\ No newline at end of file diff --git a/lib/active_relation/relations/base.rb b/lib/active_relation/relations/base.rb index 960735f07f..b4654f8f4b 100644 --- a/lib/active_relation/relations/base.rb +++ b/lib/active_relation/relations/base.rb @@ -45,6 +45,10 @@ module ActiveRelation def project(*attributes) Projection.new(self, *attributes) end + + def as(aliaz) + Alias.new(self, aliaz) + end def order(*attributes) Order.new(self, *attributes) @@ -75,8 +79,8 @@ module ActiveRelation end def to_sql(options = {}) - [ - "SELECT #{attributes.collect{ |a| a.to_sql(:use_alias => true) }.join(', ')}", + sql = [ + "SELECT #{attributes.collect{ |a| a.to_sql(:use_alias => true, :use_parens => true) }.join(', ')}", "FROM #{quote_table_name(table)}", (joins.to_sql(:quote => false) unless joins.blank?), ("WHERE #{selects.collect{|s| s.to_sql(:quote => false)}.join("\n\tAND ")}" unless selects.blank?), @@ -84,6 +88,7 @@ module ActiveRelation ("LIMIT #{limit.to_sql}" unless limit.blank?), ("OFFSET #{offset.to_sql}" unless offset.blank?) ].compact.join("\n") + options[:use_parens] ? "(#{sql})" : sql end alias_method :to_s, :to_sql @@ -95,6 +100,7 @@ module ActiveRelation def joins; nil end def limit; nil end def offset; nil end + def alias; nil 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 442224a011..26ee92b365 100644 --- a/lib/active_relation/relations/compound.rb +++ b/lib/active_relation/relations/compound.rb @@ -3,7 +3,7 @@ module ActiveRelation class Compound < Base attr_reader :relation - delegate :attributes, :attribute, :joins, :selects, :orders, :table, :inserts, :limit, :offset, :to => :relation + delegate :attributes, :attribute, :joins, :selects, :orders, :table, :inserts, :limit, :offset, :alias, :to => :relation 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 c7b99c2127..cff042dbc6 100644 --- a/lib/active_relation/relations/rename.rb +++ b/lib/active_relation/relations/rename.rb @@ -23,7 +23,7 @@ module ActiveRelation protected def attribute(name) case - when name == self.alias then schmattribute.alias(self.alias) + when name == self.alias then schmattribute.as(self.alias) when relation[name] == schmattribute then nil else relation[name] end @@ -31,7 +31,7 @@ module ActiveRelation private def substitute(a) - a == schmattribute ? a.alias(self.alias) : a + a == schmattribute ? a.as(self.alias) : a end end end diff --git a/spec/active_relation/predicates/binary_spec.rb b/spec/active_relation/predicates/binary_spec.rb index 02c72ef96d..be607efd95 100644 --- a/spec/active_relation/predicates/binary_spec.rb +++ b/spec/active_relation/predicates/binary_spec.rb @@ -6,7 +6,7 @@ describe ActiveRelation::Predicates::Binary do @relation2 = ActiveRelation::Relations::Table.new(:bar) @attribute1 = ActiveRelation::Primitives::Attribute.new(@relation1, :name1) @attribute2 = ActiveRelation::Primitives::Attribute.new(@relation2, :name2) - class ActiveRelation::Predicates::ConcreteBinary < ActiveRelation::Predicates::Binary + class ConcreteBinary < ActiveRelation::Predicates::Binary def predicate_sql "<=>" end @@ -21,20 +21,20 @@ describe ActiveRelation::Predicates::Binary do it "obtains if the concrete type of the ActiveRelation::Predicates::Binarys are identical" do ActiveRelation::Predicates::Binary.new(@attribute1, @attribute2).should == ActiveRelation::Predicates::Binary.new(@attribute1, @attribute2) - ActiveRelation::Predicates::Binary.new(@attribute1, @attribute2).should_not == ActiveRelation::Predicates::ConcreteBinary.new(@attribute1, @attribute2) + ActiveRelation::Predicates::Binary.new(@attribute1, @attribute2).should_not == ConcreteBinary.new(@attribute1, @attribute2) end end describe '#qualify' do it "distributes over the predicates and attributes" do - ActiveRelation::Predicates::ConcreteBinary.new(@attribute1, @attribute2).qualify. \ - should == ActiveRelation::Predicates::ConcreteBinary.new(@attribute1.qualify, @attribute2.qualify) + ConcreteBinary.new(@attribute1, @attribute2).qualify. \ + should == ConcreteBinary.new(@attribute1.qualify, @attribute2.qualify) end end describe '#to_sql' do it 'manufactures correct sql' do - ActiveRelation::Predicates::ConcreteBinary.new(@attribute1, @attribute2).to_sql.should be_like(""" + ConcreteBinary.new(@attribute1, @attribute2).to_sql.should be_like(""" `foo`.`name1` <=> `bar`.`name2` """) end diff --git a/spec/active_relation/primitives/aggregation_spec.rb b/spec/active_relation/primitives/aggregation_spec.rb new file mode 100644 index 0000000000..60bb4a6aa8 --- /dev/null +++ b/spec/active_relation/primitives/aggregation_spec.rb @@ -0,0 +1,25 @@ +require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper') + +describe ActiveRelation::Primitives::Aggregation do + before do + @relation1 = ActiveRelation::Relations::Table.new(:foo) + @relation2 = ActiveRelation::Relations::Table.new(:bar) + end + + describe '==' do + it 'obtains if the attribute and function sql are identical' do + @relation1[:id].sum.should == @relation1[:id].sum + @relation1[:id].sum.should_not == @relation1[:name].sum + @relation1[:id].sum.should_not == @relation1[:name].average + @relation1[:id].sum.should_not == @relation2[:id].sum + end + end + + describe '#to_sql' do + it 'manufactures sql with an aggregation function' do + @relation1[:id].maximum.to_sql.should be_like(""" + MAX(`foo`.`id`) + """) + end + end +end diff --git a/spec/active_relation/primitives/attribute_spec.rb b/spec/active_relation/primitives/attribute_spec.rb new file mode 100644 index 0000000000..2aad844659 --- /dev/null +++ b/spec/active_relation/primitives/attribute_spec.rb @@ -0,0 +1,115 @@ +require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper') + +describe ActiveRelation::Primitives::Attribute do + before do + @relation1 = ActiveRelation::Relations::Table.new(:foo) + @relation2 = ActiveRelation::Relations::Table.new(:bar) + end + + describe '#as' do + it "manufactures an aliased attributed when provided a parameter" do + @relation1[:id].as(:alias).should == ActiveRelation::Primitives::Attribute.new(@relation1, :id, :alias) + end + end + + describe '#qualified_name' do + it "manufactures an attribute name prefixed with the relation's name" do + @relation1[:id].qualified_name.should == 'foo.id' + end + end + + describe '#qualify' do + it "manufactures an attribute aliased with that attributes qualified name" do + @relation1[:id].qualify.should == @relation1[:id].qualify + end + end + + describe '==' do + it "obtains if the relation and attribute name are identical" do + ActiveRelation::Primitives::Attribute.new(@relation1, :name).should == ActiveRelation::Primitives::Attribute.new(@relation1, :name) + ActiveRelation::Primitives::Attribute.new(@relation1, :name).should_not == ActiveRelation::Primitives::Attribute.new(@relation1, :another_name) + ActiveRelation::Primitives::Attribute.new(@relation1, :name).should_not == ActiveRelation::Primitives::Attribute.new(@relation2, :name) + end + end + + describe 'predications' do + before do + @attribute1 = ActiveRelation::Primitives::Attribute.new(@relation1, :name) + @attribute2 = ActiveRelation::Primitives::Attribute.new(@relation2, :name) + end + + describe '#equals' do + it "manufactures an equality predicate" do + @attribute1.equals(@attribute2).should == ActiveRelation::Predicates::Equality.new(@attribute1, @attribute2) + end + end + + describe '#less_than' do + it "manufactures a less-than predicate" do + @attribute1.less_than(@attribute2).should == ActiveRelation::Predicates::LessThan.new(@attribute1, @attribute2) + end + end + + describe '#less_than_or_equal_to' do + it "manufactures a less-than or equal-to predicate" do + @attribute1.less_than_or_equal_to(@attribute2).should == ActiveRelation::Predicates::LessThanOrEqualTo.new(@attribute1, @attribute2) + end + end + + describe '#greater_than' do + it "manufactures a greater-than predicate" do + @attribute1.greater_than(@attribute2).should == ActiveRelation::Predicates::GreaterThan.new(@attribute1, @attribute2) + end + end + + describe '#greater_than_or_equal_to' do + it "manufactures a greater-than or equal to predicate" do + @attribute1.greater_than_or_equal_to(@attribute2).should == ActiveRelation::Predicates::GreaterThanOrEqualTo.new(@attribute1, @attribute2) + end + end + + describe '#matches' do + it "manufactures a match predicate" do + @attribute1.matches(/.*/).should == ActiveRelation::Predicates::Match.new(@attribute1, @attribute2) + 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 diff --git a/spec/active_relation/relations/base_spec.rb b/spec/active_relation/relations/base_spec.rb index 689e3ecadb..db112e679a 100644 --- a/spec/active_relation/relations/base_spec.rb +++ b/spec/active_relation/relations/base_spec.rb @@ -49,13 +49,19 @@ describe ActiveRelation::Relations::Base do end it "manufactures a projection relation" do - @relation1.project(@attribute1, @attribute2).should be_kind_of(ActiveRelation::Relations::Projection) + @relation1.project(@attribute1, @attribute2).should == ActiveRelation::Relations::Projection.new(@relation1, @attribute1, @attribute2) + end + end + + describe '#as' do + it "manufactures an alias relation" do + @relation1.as(:thucydides).should == ActiveRelation::Relations::Alias.new(@relation1, :thucydides) end end describe '#rename' do it "manufactures a rename relation" do - @relation1.rename(@attribute1, :foo).should be_kind_of(ActiveRelation::Relations::Rename) + @relation1.rename(@attribute1, :foo).should == ActiveRelation::Relations::Rename.new(@relation1, @attribute1 => :foo) end end @@ -65,11 +71,11 @@ describe ActiveRelation::Relations::Base do end it "manufactures a selection relation" do - @relation1.select(@predicate).should be_kind_of(ActiveRelation::Relations::Selection) + @relation1.select(@predicate).should == ActiveRelation::Relations::Selection.new(@relation1, @predicate) end it "accepts arbitrary strings" do - @relation1.select("arbitrary").should be_kind_of(ActiveRelation::Relations::Selection) + @relation1.select("arbitrary").should == ActiveRelation::Relations::Selection.new(@relation1, "arbitrary") end end @@ -93,4 +99,12 @@ describe ActiveRelation::Relations::Base do end end end + + describe '#to_sql' do + it "manufactures sql with scalar selects" do + @relation1.as(:tobias).to_sql(:use_parens => true).should be_like(""" + (SELECT `foo`.`name`, `foo`.`id` FROM `foo`) AS tobias + """) + 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 new file mode 100644 index 0000000000..f383ff4dfd --- /dev/null +++ b/spec/active_relation/relations/compound_spec.rb @@ -0,0 +1,13 @@ +require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper') + +describe ActiveRelation::Relations::Compound do + before do + @relation = ActiveRelation::Relations::Table.new(:users) + + class ConcreteCompound < ActiveRelation::Relations::Compound + def initialize(relation) + @relation = relation + end + end + end +end
\ No newline at end of file diff --git a/spec/active_relation/relations/projection_spec.rb b/spec/active_relation/relations/projection_spec.rb index 8ba571e06c..6ffdeb8e09 100644 --- a/spec/active_relation/relations/projection_spec.rb +++ b/spec/active_relation/relations/projection_spec.rb @@ -17,7 +17,7 @@ describe ActiveRelation::Relations::Projection do end describe '#qualify' do - it "distributes over teh relation and attributes" do + it "distributes over the relation and attributes" do ActiveRelation::Relations::Projection.new(@relation1, @attribute1).qualify. \ should == ActiveRelation::Relations::Projection.new(@relation1.qualify, @attribute1.qualify) end diff --git a/spec/active_relation/relations/rename_spec.rb b/spec/active_relation/relations/rename_spec.rb index e52abab3a1..76b7069190 100644 --- a/spec/active_relation/relations/rename_spec.rb +++ b/spec/active_relation/relations/rename_spec.rb @@ -26,14 +26,14 @@ describe ActiveRelation::Relations::Rename do describe '#attributes' do it "manufactures a list of attributes with the renamed attribute aliased" do ActiveRelation::Relations::Rename.new(@relation, @relation[:id] => :schmid).attributes.should == - (@relation.attributes - [@relation[:id]]) + [@relation[:id].alias(:schmid)] + (@relation.attributes - [@relation[:id]]) + [@relation[:id].as(:schmid)] end end describe '[]' do it 'indexes attributes by alias' do @renamed_relation[:id].should be_nil - @renamed_relation[:schmid].should == @relation[:id].alias(:schmid) + @renamed_relation[:schmid].should == @relation[:id].as(:schmid) end end |