aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/active_relation/primitives/attribute.rb6
-rw-r--r--lib/active_relation/relations.rb3
-rw-r--r--lib/active_relation/relations/alias.rb19
-rw-r--r--lib/active_relation/relations/base.rb10
-rw-r--r--lib/active_relation/relations/compound.rb2
-rw-r--r--lib/active_relation/relations/rename.rb4
-rw-r--r--spec/active_relation/predicates/binary_spec.rb10
-rw-r--r--spec/active_relation/primitives/aggregation_spec.rb25
-rw-r--r--spec/active_relation/primitives/attribute_spec.rb115
-rw-r--r--spec/active_relation/relations/base_spec.rb22
-rw-r--r--spec/active_relation/relations/compound_spec.rb13
-rw-r--r--spec/active_relation/relations/projection_spec.rb2
-rw-r--r--spec/active_relation/relations/rename_spec.rb4
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