aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/active_relation/primitives.rb2
-rw-r--r--lib/active_relation/primitives/aggregation.rb35
-rw-r--r--lib/active_relation/primitives/attribute.rb14
-rw-r--r--lib/active_relation/relations.rb3
-rw-r--r--lib/active_relation/relations/aggregation.rb27
-rw-r--r--lib/active_relation/relations/alias.rb12
-rw-r--r--lib/active_relation/relations/compound.rb19
-rw-r--r--lib/active_relation/relations/group.rb21
-rw-r--r--lib/active_relation/relations/join.rb18
-rw-r--r--lib/active_relation/relations/projection.rb1
-rw-r--r--lib/active_relation/relations/relation.rb46
-rw-r--r--lib/active_relation/relations/rename.rb40
-rw-r--r--lib/active_relation/relations/schmoin.rb43
-rw-r--r--lib/active_relation/relations/table.rb12
-rw-r--r--spec/active_relation/predicates/equality_spec.rb3
-rw-r--r--spec/active_relation/primitives/aggregation_spec.rb62
-rw-r--r--spec/active_relation/primitives/attribute_spec.rb55
-rw-r--r--spec/active_relation/relations/alias_spec.rb19
-rw-r--r--spec/active_relation/relations/compound_spec.rb41
-rw-r--r--spec/active_relation/relations/group_spec.rb35
-rw-r--r--spec/active_relation/relations/join_spec.rb18
-rw-r--r--spec/active_relation/relations/projection_spec.rb4
-rw-r--r--spec/active_relation/relations/relation_spec.rb11
-rw-r--r--spec/active_relation/relations/rename_spec.rb58
-rw-r--r--spec/active_relation/relations/schmoin_spec.rb24
-rw-r--r--spec/active_relation/relations/table_spec.rb30
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