diff options
-rw-r--r-- | lib/active_relation/extensions.rb | 1 | ||||
-rw-r--r-- | lib/active_relation/extensions/array.rb | 4 | ||||
-rw-r--r-- | lib/active_relation/extensions/range.rb | 9 | ||||
-rw-r--r-- | lib/active_relation/predicates.rb | 14 | ||||
-rw-r--r-- | lib/active_relation/primitives/attribute.rb | 4 | ||||
-rw-r--r-- | lib/active_relation/primitives/value.rb | 2 | ||||
-rw-r--r-- | lib/active_relation/relations/relation.rb | 21 | ||||
-rw-r--r-- | lib/active_relation/sql.rb | 14 | ||||
-rw-r--r-- | spec/active_relation/unit/predicates/binary_spec.rb | 44 | ||||
-rw-r--r-- | spec/active_relation/unit/predicates/in_spec.rb | 58 | ||||
-rw-r--r-- | spec/active_relation/unit/primitives/attribute_spec.rb | 6 | ||||
-rw-r--r-- | spec/active_relation/unit/relations/relation_spec.rb | 20 |
12 files changed, 126 insertions, 71 deletions
diff --git a/lib/active_relation/extensions.rb b/lib/active_relation/extensions.rb index 7268a5549b..21d6724004 100644 --- a/lib/active_relation/extensions.rb +++ b/lib/active_relation/extensions.rb @@ -2,3 +2,4 @@ require 'active_relation/extensions/object' require 'active_relation/extensions/class' require 'active_relation/extensions/array' require 'active_relation/extensions/hash' +require 'active_relation/extensions/range'
\ No newline at end of file diff --git a/lib/active_relation/extensions/array.rb b/lib/active_relation/extensions/array.rb index c07819d35f..2af5832707 100644 --- a/lib/active_relation/extensions/array.rb +++ b/lib/active_relation/extensions/array.rb @@ -6,4 +6,8 @@ class Array def to_sql(formatter = nil) "(" + collect { |e| e.to_sql(formatter) }.join(', ') + ")" end + + def predicate_sql + "IN" + end end
\ No newline at end of file diff --git a/lib/active_relation/extensions/range.rb b/lib/active_relation/extensions/range.rb new file mode 100644 index 0000000000..0218a0ab44 --- /dev/null +++ b/lib/active_relation/extensions/range.rb @@ -0,0 +1,9 @@ +class Range + def to_sql(formatter = nil) + formatter.range self.begin, self.end + end + + def predicate_sql + "BETWEEN" + end +end
\ No newline at end of file diff --git a/lib/active_relation/predicates.rb b/lib/active_relation/predicates.rb index 98a966507f..f68ec991c3 100644 --- a/lib/active_relation/predicates.rb +++ b/lib/active_relation/predicates.rb @@ -76,18 +76,10 @@ module ActiveRelation class Match < Binary alias_method :regexp, :operand2 - - def initialize(operand1, regexp) - @operand1, @regexp = operand1, regexp - end end - - class RelationInclusion < Binary - alias_method :relation, :operand2 - + + class In < Binary protected - def predicate_sql - 'IN' - end + delegate :predicate_sql, :to => :operand2 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 0ddbbb5cd4..ddf5ef5e07 100644 --- a/lib/active_relation/primitives/attribute.rb +++ b/lib/active_relation/primitives/attribute.rb @@ -85,6 +85,10 @@ module ActiveRelation def matches(regexp) Match.new(self, regexp) end + + def in(array) + In.new(self, array) + end end include Predications diff --git a/lib/active_relation/primitives/value.rb b/lib/active_relation/primitives/value.rb index 131610f2e9..aeee89dc3b 100644 --- a/lib/active_relation/primitives/value.rb +++ b/lib/active_relation/primitives/value.rb @@ -2,6 +2,8 @@ module ActiveRelation class Value attr_reader :value, :relation + delegate :predicate_sql, :to => :value + def initialize(value, relation) @value, @relation = value, relation end diff --git a/lib/active_relation/relations/relation.rb b/lib/active_relation/relations/relation.rb index 8c93f948f7..1364911f0c 100644 --- a/lib/active_relation/relations/relation.rb +++ b/lib/active_relation/relations/relation.rb @@ -37,10 +37,6 @@ module ActiveRelation end end - def include?(attribute) - RelationInclusion.new(attribute, self) - end - def select(*predicates) Selection.new(self, *predicates.collect {|p| p.bind(self)}) end @@ -94,13 +90,16 @@ module ActiveRelation end include Operations - def aggregation? - false - end + module Externalizable + def aggregation? + false + end - def alias? - false + def alias? + false + end end + include Externalizable def to_sql(formatter = Sql::SelectStatement.new(engine)) formatter.select [ @@ -116,6 +115,10 @@ module ActiveRelation end alias_method :to_s, :to_sql + def predicate_sql + "IN" + end + def call(connection = engine.connection) connection.select_all(to_sql) end diff --git a/lib/active_relation/sql.rb b/lib/active_relation/sql.rb index 85dd591860..027356d4d7 100644 --- a/lib/active_relation/sql.rb +++ b/lib/active_relation/sql.rb @@ -35,7 +35,11 @@ module ActiveRelation "#{quote_table_name(relation_name)}.#{quote_column_name(attribute_name)}" end - def value(value, column = nil) + def value(value) + value.to_sql(self) + end + + def scalar(value, column = nil) quote(value, column) end @@ -61,10 +65,6 @@ module ActiveRelation @attribute, @engine = attribute, attribute.engine end - def value(value) - value.to_sql(self) - end - def scalar(scalar) quote(scalar, @attribute.column) end @@ -72,6 +72,10 @@ module ActiveRelation def array(array) "(" + array.collect { |e| e.to_sql(self) }.join(', ') + ")" end + + def range(left, right) + "#{left} AND #{right}" + end end class Value < WhereCondition diff --git a/spec/active_relation/unit/predicates/binary_spec.rb b/spec/active_relation/unit/predicates/binary_spec.rb index b63472a836..04f8d4f305 100644 --- a/spec/active_relation/unit/predicates/binary_spec.rb +++ b/spec/active_relation/unit/predicates/binary_spec.rb @@ -6,7 +6,6 @@ module ActiveRelation @relation = Table.new(:users) @attribute1 = @relation[:id] @attribute2 = @relation[:name] - @value = "1-asdf".bind(@relation) class ConcreteBinary < Binary def predicate_sql "<=>" @@ -24,6 +23,10 @@ module ActiveRelation end describe 'when relating an attribute and a value' do + before do + @value = "1-asdf".bind(@relation) + end + describe 'when relating to an integer attribute' do it 'formats values as integers' do ConcreteBinary.new(@attribute1, @value).to_sql.should be_like(" @@ -43,49 +46,16 @@ module ActiveRelation describe 'when relating two values' do before do + @value = "1-asdf".bind(@relation) @another_value = 2.bind(@relation) end - it 'quotes values appropriate to their type' do + it 'formats values appropos of their type' do ConcreteBinary.new(string = @value, integer = @another_value).to_sql.should be_like(" '1-asdf' <=> 2 ") end end - - describe 'when relating to an array' do - describe 'when the array\'s elements are the same type as the attribute' do - before do - @array = [1, 2, 3] - end - - it 'manufactures sql with a comma separated list' do - ConcreteBinary.new(@attribute1, @array.bind(@relation)).to_sql.should be_like(" - `users`.`id` <=> (1, 2, 3) - ") - end - end - - describe 'when the array\'s elements are not same type as the attribute' do - before do - @array = ['1-asdf', 2, 3] - end - - it 'formats values in the array as the type of the attribute' do - ConcreteBinary.new(@attribute1, @array.bind(@relation)).to_sql.should be_like(" - `users`.`id` <=> (1, 2, 3) - ") - end - end - end - - describe 'when relating to a relation' do - it 'manufactures sql with a subselect' do - ConcreteBinary.new(@attribute1, @relation).to_sql.should be_like(" - `users`.`id` <=> (SELECT `users`.`id`, `users`.`name` FROM `users`) - ") - end - end end describe '==' do @@ -94,7 +64,7 @@ module ActiveRelation Binary.new(@attribute1, @attribute2).should_not == Binary.new(@attribute1, @attribute1) end - it "obtains if the concrete type of the Predicates::Binarys are identical" do + it "obtains if the concrete type of the predicates are identical" do Binary.new(@attribute1, @attribute2).should == Binary.new(@attribute1, @attribute2) Binary.new(@attribute1, @attribute2).should_not == ConcreteBinary.new(@attribute1, @attribute2) end diff --git a/spec/active_relation/unit/predicates/in_spec.rb b/spec/active_relation/unit/predicates/in_spec.rb new file mode 100644 index 0000000000..9e60c29ce0 --- /dev/null +++ b/spec/active_relation/unit/predicates/in_spec.rb @@ -0,0 +1,58 @@ +require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper') + +module ActiveRelation + describe In do + before do + @relation = Table.new(:users) + @attribute = @relation[:id] + end + + describe '#to_sql' do + describe 'when relating to an array' do + describe 'when the array\'s elements are the same type as the attribute' do + before do + @array = [1, 2, 3].bind(@relation) + end + + it 'manufactures sql with a comma separated list' do + In.new(@attribute, @array).to_sql.should be_like(" + `users`.`id` IN (1, 2, 3) + ") + end + end + + describe 'when the array\'s elements are not same type as the attribute' do + before do + @array = ['1-asdf', 2, 3].bind(@relation) + end + + it 'formats values in the array as the type of the attribute' do + In.new(@attribute, @array).to_sql.should be_like(" + `users`.`id` IN (1, 2, 3) + ") + end + end + end + + describe 'when relating to a range' do + before do + @range = (1..2).bind(@relation) + end + + it 'manufactures sql with a between' do + In.new(@attribute, @range).to_sql.should be_like(" + `users`.`id` BETWEEN 1 AND 2 + ") + end + end + + describe 'when relating to a relation' do + it 'manufactures sql with a subselect' do + In.new(@attribute, @relation).to_sql.should be_like(" + `users`.`id` IN (SELECT `users`.`id`, `users`.`name` FROM `users`) + ") + end + end + end + end +end
\ No newline at end of file diff --git a/spec/active_relation/unit/primitives/attribute_spec.rb b/spec/active_relation/unit/primitives/attribute_spec.rb index a0f6cde8f7..2806d26330 100644 --- a/spec/active_relation/unit/primitives/attribute_spec.rb +++ b/spec/active_relation/unit/primitives/attribute_spec.rb @@ -130,6 +130,12 @@ module ActiveRelation @attribute.matches(/.*/).should == Match.new(@attribute, /.*/) end end + + describe '#in' do + it "manufactures an in predicate" do + @attribute.in(1..30).should == In.new(@attribute, 1..30) + end + end end describe Attribute::Expressions do diff --git a/spec/active_relation/unit/relations/relation_spec.rb b/spec/active_relation/unit/relations/relation_spec.rb index b5e204abcf..d434a1e317 100644 --- a/spec/active_relation/unit/relations/relation_spec.rb +++ b/spec/active_relation/unit/relations/relation_spec.rb @@ -30,18 +30,20 @@ module ActiveRelation end end - describe '#include?' do - it "manufactures an inclusion predicate" do - @relation.include?(@attribute1).should be_kind_of(RelationInclusion) + describe Relation::Externalizable do + describe '#aggregation?' do + it "returns false" do + @relation.should_not be_aggregation + end end - end - - describe '#aggregation?' do - it "returns false" do - @relation.should_not be_aggregation + + describe '#alias?' do + it "returns false" do + @relation.should_not be_alias + end end end - + describe Relation::Operations do describe 'joins' do before do |