aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kallen <nkallen@nick-kallens-computer-2.local>2008-03-11 23:22:26 -0700
committerNick Kallen <nkallen@nick-kallens-computer-2.local>2008-03-11 23:22:26 -0700
commit12ef6a5ad15078d2f634d3c6cdfc453848f90122 (patch)
tree426f7fee7383bda64c050bc125733ba48e592d18
parenta29ceffc9476c99ff02f0617d2e38627c526bac2 (diff)
downloadrails-12ef6a5ad15078d2f634d3c6cdfc453848f90122.tar.gz
rails-12ef6a5ad15078d2f634d3c6cdfc453848f90122.tar.bz2
rails-12ef6a5ad15078d2f634d3c6cdfc453848f90122.zip
refactored session's interaction with engine/connection
- follows law of demeter - Table.engine uses AR::Base adapter
-rw-r--r--TODO48
-rw-r--r--lib/active_relation/relations/deletion.rb4
-rw-r--r--lib/active_relation/relations/insertion.rb4
-rw-r--r--lib/active_relation/relations/relation.rb4
-rw-r--r--lib/active_relation/relations/update.rb4
-rw-r--r--lib/active_relation/sessions/session.rb8
-rw-r--r--spec/active_relation/unit/relations/deletion_spec.rb8
-rw-r--r--spec/active_relation/unit/relations/insertion_spec.rb10
-rw-r--r--spec/active_relation/unit/relations/relation_spec.rb10
-rw-r--r--spec/active_relation/unit/relations/update_spec.rb9
-rw-r--r--spec/active_relation/unit/session/session_spec.rb18
-rw-r--r--spec/spec_helper.rb2
12 files changed, 113 insertions, 16 deletions
diff --git a/TODO b/TODO
new file mode 100644
index 0000000000..45bc9c4f2f
--- /dev/null
+++ b/TODO
@@ -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