diff options
-rw-r--r-- | TODO | 48 | ||||
-rw-r--r-- | lib/active_relation/relations/deletion.rb | 4 | ||||
-rw-r--r-- | lib/active_relation/relations/insertion.rb | 4 | ||||
-rw-r--r-- | lib/active_relation/relations/relation.rb | 4 | ||||
-rw-r--r-- | lib/active_relation/relations/update.rb | 4 | ||||
-rw-r--r-- | lib/active_relation/sessions/session.rb | 8 | ||||
-rw-r--r-- | spec/active_relation/unit/relations/deletion_spec.rb | 8 | ||||
-rw-r--r-- | spec/active_relation/unit/relations/insertion_spec.rb | 10 | ||||
-rw-r--r-- | spec/active_relation/unit/relations/relation_spec.rb | 10 | ||||
-rw-r--r-- | spec/active_relation/unit/relations/update_spec.rb | 9 | ||||
-rw-r--r-- | spec/active_relation/unit/session/session_spec.rb | 18 | ||||
-rw-r--r-- | spec/spec_helper.rb | 2 |
12 files changed, 113 insertions, 16 deletions
@@ -0,0 +1,48 @@ +todo: +- clarify distinction between engine and connection: an engine is a connection pool, plus the quoting operations +- #relation is now on scalar, attribute and relation; you must admit it's name is confusing given that e.g., relation already has a strategy (Sql::Relation) ... should it be called predicate strategy? operand1.to_sql(operand2.predicate) maybe prefer operand1.cast(operand2) or project or in light of +- clean up integration tests in join - i find the aggregate stuff too integrationy; unit testing would be better +- test relation, table reset +- cache expiry on write + - rewrite of querycache test in light of this +- relation inclusion when given an array (1,2,3,4) should quote the elements using the appropriate quoting strategy taken from the attribute + - descend on array, along with bind written in terms of it +- standardize quoting + - use strings everywhere, not symbols ? +- rename and test sql strategies + - the parallel names are confusing since it's not obvious what's what. plus, we lack unit tests; the biggest complaint is a lack of clarity concerning what purpose these serve in the system. Unit tests wont illustrate much unless we use concrete examples. +- rename the tion (Selection) classes so that words that don't end in tion don't seem inconsistent +- re-evaluate bind + +done: +. Relation <=> Relation -> InnerJoinOperation +. Relation << Relation -> LeftOuterJoinOperation +. InnerJoinOperation.on(*Predicate) -> InnerJoinRelation +. LeftOuterJoinOperation.on(*Predicate) -> LeftOuterJoinRelation +. Relation[Symbol] -> Attribute +. Relation[Range] -> Relation +. Attribute == Attribute -> EqualityPredicate +. Attribute >= Attribute -> GreaterThanOrEqualToPredicate +. Relation.include?(Column) -> Predicate +. Relation.project(*Column) -> ProjectionRelation +. Relation.select(*Predicate) -> SelectionRelation +. Relation.order(*Column) -> OrderRelation +. #to_sql +. Remove Builder +. Namespace +. Audit SqlAlchemy for missing features +- Generalized denormalizations on any aggregation (count, yes, but also max, min, average) +- Remove operator overloading of << and <=> for joins. Make it just foo.join(bar) and foo.outer_join(bar). +- Remove operator overloading of == for predicates. make it a.equals(b) (note lack of question mark). +- hookup more predicates (=, <=, =>) +- get some basic aggregations working: users.project(user[:points].max) +- Alias Table Names +- When joining with any sort of aggregation, it needs to be a nested select +- get a scalar select working: users.project(users[:name], addresses.select(addresses[:user_id] == users[:id]).project(addresses[:id].count)) +- Session +- sublimate scalars to deal with the fact that they must be quoted per engine +- clean-up singleton monstrosity +- extract hashing module +- hash custom matcher +- make session engine stuff follow laws of demeter - currently doing some odd method chaining? rethink who is responsible for what + - session just calls execute, passing in a connection; by default it gets a connection from the relation. diff --git a/lib/active_relation/relations/deletion.rb b/lib/active_relation/relations/deletion.rb index f3d81baf27..c5906e8bc8 100644 --- a/lib/active_relation/relations/deletion.rb +++ b/lib/active_relation/relations/deletion.rb @@ -12,6 +12,10 @@ module ActiveRelation ].compact.join("\n") end + def call(connection = engine.connection) + connection.delete(to_sql) + end + def ==(other) self.class == other.class and relation == other.relation diff --git a/lib/active_relation/relations/insertion.rb b/lib/active_relation/relations/insertion.rb index 16fe3d5f46..036db1a319 100644 --- a/lib/active_relation/relations/insertion.rb +++ b/lib/active_relation/relations/insertion.rb @@ -15,6 +15,10 @@ module ActiveRelation ].join("\n") end + def call(connection = engine.connection) + connection.insert(to_sql) + end + def ==(other) self.class == other.class and relation == other.relation and diff --git a/lib/active_relation/relations/relation.rb b/lib/active_relation/relations/relation.rb index f9823bf92d..69935a7be0 100644 --- a/lib/active_relation/relations/relation.rb +++ b/lib/active_relation/relations/relation.rb @@ -115,6 +115,10 @@ module ActiveRelation ].compact.join("\n"), self.alias end alias_method :to_s, :to_sql + + def call(connection = engine.connection) + connection.select_all(to_sql) + end def attribute_for_name(name) attributes.detect { |a| a.alias_or_name.to_s == name.to_s } diff --git a/lib/active_relation/relations/update.rb b/lib/active_relation/relations/update.rb index c50919af3e..0914cda035 100644 --- a/lib/active_relation/relations/update.rb +++ b/lib/active_relation/relations/update.rb @@ -16,6 +16,10 @@ module ActiveRelation ].join("\n") end + def call(connection = engine.connection) + connection.update(to_sql) + end + def ==(other) self.class == other.class and relation == other.relation and diff --git a/lib/active_relation/sessions/session.rb b/lib/active_relation/sessions/session.rb index 4bdbe69978..fe917a0e4d 100644 --- a/lib/active_relation/sessions/session.rb +++ b/lib/active_relation/sessions/session.rb @@ -25,22 +25,22 @@ module ActiveRelation module CRUD def create(insert) - insert.engine.insert(insert.to_sql) + insert.call(insert.engine.connection) end def read(select) @read ||= Hash.new do |hash, select| - hash[select] = select.engine.select_all(select.to_sql) + hash[select] = select.call(select.engine.connection) end @read[select] end def update(update) - update.engine.update(update.to_sql) + update.call(update.engine.connection) end def delete(delete) - delete.engine.delete(delete.to_sql) + delete.call(delete.engine.connection) end end include CRUD diff --git a/spec/active_relation/unit/relations/deletion_spec.rb b/spec/active_relation/unit/relations/deletion_spec.rb index 1f14ae5d34..27d879e96f 100644 --- a/spec/active_relation/unit/relations/deletion_spec.rb +++ b/spec/active_relation/unit/relations/deletion_spec.rb @@ -22,5 +22,13 @@ module ActiveRelation ") end end + + describe '#call' do + it 'executes a delete on the connection' do + deletion = Deletion.new(@relation) + mock(connection = Object.new).delete(deletion.to_sql) + deletion.call(connection) + end + end end end
\ No newline at end of file diff --git a/spec/active_relation/unit/relations/insertion_spec.rb b/spec/active_relation/unit/relations/insertion_spec.rb index 91bf7773c1..f081743c50 100644 --- a/spec/active_relation/unit/relations/insertion_spec.rb +++ b/spec/active_relation/unit/relations/insertion_spec.rb @@ -4,16 +4,24 @@ module ActiveRelation describe Insertion do before do @relation = Table.new(:users) + @insertion = Insertion.new(@relation, @relation[:name] => "nick".bind(@relation)) end describe '#to_sql' do it 'manufactures sql inserting the data for one item' do - Insertion.new(@relation, @relation[:name] => "nick".bind(@relation)).to_sql.should be_like(" + @insertion.to_sql.should be_like(" INSERT INTO `users` (`users`.`name`) VALUES ('nick') ") end end + + describe '#call' do + it 'executes an insert on the connection' do + mock(connection = Object.new).insert(@insertion.to_sql) + @insertion.call(connection) + end + end end end
\ No newline at end of file diff --git a/spec/active_relation/unit/relations/relation_spec.rb b/spec/active_relation/unit/relations/relation_spec.rb index 8f35760801..2e9f7fd3c8 100644 --- a/spec/active_relation/unit/relations/relation_spec.rb +++ b/spec/active_relation/unit/relations/relation_spec.rb @@ -69,7 +69,7 @@ module ActiveRelation describe '#as' do it "manufactures an alias relation" do - @relation.as(:thucydides).should == Alias.new(@relation, :thucydides) + @relation.as(:paul).should == Alias.new(@relation, :paul) end end @@ -99,6 +99,14 @@ module ActiveRelation end end + describe '#call' do + it 'executes a select_all on the connection' do + mock(connection = Object.new).select_all(@relation.to_sql) + @relation.call(connection) + end + end + + describe '#aggregate' do before do @expression1 = @attribute1.sum diff --git a/spec/active_relation/unit/relations/update_spec.rb b/spec/active_relation/unit/relations/update_spec.rb index cad14fd5ec..848760de83 100644 --- a/spec/active_relation/unit/relations/update_spec.rb +++ b/spec/active_relation/unit/relations/update_spec.rb @@ -22,5 +22,14 @@ module ActiveRelation ") end end + + describe '#call' do + it 'executes an update on the connection' do + update = Update.new(@relation, @relation[:name] => "nick".bind(@relation)) + mock(connection = Object.new).update(update.to_sql) + update.call(connection) + end + end + end end
\ No newline at end of file diff --git a/spec/active_relation/unit/session/session_spec.rb b/spec/active_relation/unit/session/session_spec.rb index 89d96ef323..9fba6cc6b2 100644 --- a/spec/active_relation/unit/session/session_spec.rb +++ b/spec/active_relation/unit/session/session_spec.rb @@ -35,39 +35,39 @@ module ActiveRelation @insert = Insertion.new(@relation, @relation[:name] => 'nick'.bind(@relation)) @update = Update.new(@relation, @relation[:name] => 'nick'.bind(@relation)) @delete = Deletion.new(@relation) - @select = @relation + @read = @relation end describe '#create' do it "executes an insertion on the connection" do - mock(@insert.engine).insert(@insert.to_sql) + mock(@insert).call(@insert.engine.connection) @session.create(@insert) end end describe '#read' do it "executes an selection on the connection" do - mock(@select.engine).select_all(@select.to_sql).once - @session.read(@select) + mock(@read).call(@read.engine.connection) + @session.read(@read) end it "is memoized" do - mock(@select.engine).select_all(@select.to_sql).once - @session.read(@select) - @session.read(@select) + mock(@read).call(@read.engine.connection).once + @session.read(@read) + @session.read(@read) end end describe '#update' do it "executes an update on the connection" do - mock(@update.engine).update(@update.to_sql) + mock(@update).call(@update.engine.connection) @session.update(@update) end end describe '#delete' do it "executes a delete on the connection" do - mock(@delete.engine).delete(@delete.to_sql) + mock(@delete).call(@delete.engine.connection) @session.delete(@delete) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6d00064e81..01a703a7d4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -29,6 +29,6 @@ Spec::Runner.configure do |config| config.include(BeLikeMatcher, HashTheSameAsMatcher) config.mock_with :rr config.before do - ActiveRelation::Table.engine = ActiveRecord::Base.connection + ActiveRelation::Table.engine = ActiveRelation::Engine.new(ActiveRecord::Base) end end
\ No newline at end of file |