1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Introduced concept of session. It does not yet support multiple databases, nor transactions, but it's a start!

This commit is contained in:
Nick Kallen 2008-02-23 19:29:18 -08:00
parent f10d3be703
commit 51fdd769c0
13 changed files with 189 additions and 70 deletions

View file

@ -11,4 +11,5 @@ require 'active_relation/relations/rename'
require 'active_relation/relations/deletion'
require 'active_relation/relations/insertion'
require 'active_relation/relations/update'
require 'active_relation/relations/alias'
require 'active_relation/relations/alias'
require 'active_relation/sessions/session'

View file

@ -10,6 +10,11 @@ module ActiveRelation
"FROM #{table_sql}",
("WHERE #{selects.collect(&:to_sql).join('\n\tAND ')}" unless selects.blank?)
].compact.join("\n")
end
end
def ==(other)
self.class == other.class and
relation == other.relation
end
end
end

View file

@ -11,13 +11,14 @@ module ActiveRelation
"INSERT",
"INTO #{table_sql}",
"(#{record.keys.collect(&:to_sql).join(', ')})",
"VALUES #{inserts.collect(&:to_sql).join(', ')}"
"VALUES #{record.to_sql}"
].join("\n")
end
protected
def inserts
relation.inserts + [record]
end
def ==(other)
self.class == other.class and
relation == other.relation and
record == other.record
end
end
end

View file

@ -2,18 +2,22 @@ module ActiveRelation
class Relation
include Sql::Quoting
module Iteration
include Enumerable
def session
Session.instance
end
module Enumerable
include ::Enumerable
def each(&block)
connection.select_all(to_s).each(&block)
session.read(self).each(&block)
end
def first
connection.select_one(to_s)
session.read(self).first
end
end
include Iteration
include Enumerable
module Operations
def join(other)
@ -58,18 +62,25 @@ module ActiveRelation
def rename(attribute, aliaz)
Rename.new(self, attribute => aliaz)
end
def insert(record)
Insertion.new(self, record)
end
def delete
Deletion.new(self)
end
def aggregate(*expressions)
AggregateOperation.new(self, expressions)
end
module Writes
def insert(record)
session.create Insertion.new(self, record); self
end
def update(assignments)
session.update Update.new(self, assignments); self
end
def delete
session.delete Deletion.new(self); self
end
end
include Writes
JoinOperation = Struct.new(:join_sql, :relation1, :relation2) do
def on(*predicates)
@ -84,7 +95,7 @@ module ActiveRelation
end
end
include Operations
def aggregation?
false
end

View file

@ -12,6 +12,12 @@ module ActiveRelation
assignments.inject([]) { |assignments, (attribute, value)| assignments << "#{attribute.to_sql} = #{value.to_sql}" }.join(" "),
("WHERE #{selects.collect(&:to_sql).join('\n\tAND ')}" unless selects.blank?)
].join("\n")
end
end
def ==(other)
self.class == other.class and
relation == other.relation and
assignments == other.assignments
end
end
end

View file

@ -0,0 +1,38 @@
require 'singleton'
module ActiveRelation
class Session
include Singleton
module CRUD
def connection
ActiveRecord::Base.connection
end
def create(insert)
connection.insert(insert.to_sql)
end
def read(select)
connection.select_all(select.to_sql)
end
def update(update)
connection.update(update.to_sql)
end
def delete(delete)
connection.delete(delete.to_sql)
end
end
include CRUD
module Transactions
end
include Transactions
module UnitOfWork
end
include UnitOfWork
end
end

View file

@ -2,7 +2,7 @@ module ActiveRelation
module Sql
module Quoting
def connection
ActiveRecord::Base.connection
Session.instance.connection
end
delegate :quote_table_name, :quote_column_name, :quote, :to => :connection

View file

@ -136,24 +136,6 @@ describe 'ActiveRelation', 'A proposed refactoring to ActiveRecord, introducing
""")
end
describe 'write operations' do
it 'generates the query for user.destroy' do
@user.delete.to_sql.should be_like("""
DELETE
FROM `users`
WHERE `users`.`id` = 1
""")
end
it 'generates an efficient query for two User.creates -- UnitOfWork is within reach!' do
@users.insert(@users[:name] => "humpty").insert(@users[:name] => "dumpty").to_sql.should be_like("""
INSERT
INTO `users`
(`users`.`name`) VALUES ('humpty'), ('dumpty')
""")
end
end
describe 'with_scope' do
it 'obviates the need for with_scope merging logic since, e.g.,
`with_scope :conditions => ...` is just a #select operation on the relation' do

View file

@ -14,15 +14,6 @@ module ActiveRelation
(`users`.`name`) VALUES ('nick')
""")
end
it 'manufactures sql inserting the data for multiple items' do
nested_insertion = Insertion.new(@relation, @relation[:name] => "cobra")
Insertion.new(nested_insertion, nested_insertion[:name] => "commander").to_sql.should be_like("""
INSERT
INTO `users`
(`users`.`name`) VALUES ('cobra'), ('commander')
""")
end
end
end
end

View file

@ -36,13 +36,13 @@ module ActiveRelation
end
end
describe '#Expression?' do
describe '#aggregation?' do
it "returns false" do
@relation.should_not be_aggregation
end
end
describe 'read operations' do
describe Relation::Operations do
describe 'joins' do
before do
@predicate = @relation[:id].equals(@relation[:id])
@ -105,19 +105,34 @@ module ActiveRelation
should == Aggregation.new(@relation, :expressions => [@expresion, @expression2], :groupings => [@attribute1, @attribute2])
end
end
end
describe 'write operations' do
describe '#delete' do
it 'manufactures a deletion relation' do
@relation.delete.should be_kind_of(Deletion)
describe Relation::Operations::Writes do
describe '#delete' do
it 'manufactures a deletion relation' do
mock(Session.instance).delete(Deletion.new(@relation))
@relation.delete.should == @relation
end
end
describe '#insert' do
it 'manufactures an insertion relation' do
mock(Session.instance).create(Insertion.new(@relation, record = {@relation[:name] => 'carl'}))
@relation.insert(record).should == @relation
end
end
describe '#update' do
it 'manufactures an update relation' do
mock(Session.instance).update(Update.new(@relation, assignments = {@relation[:name] => 'bob'}))
@relation.update(assignments).should == @relation
end
end
end
describe '#insert' do
it 'manufactures an insertion relation' do
@relation.insert(record = {:id => 1}).should be_kind_of(Insertion)
end
end
describe Relation::Enumerable do
it "is enumerable" do
pending
end
end
end

View file

@ -21,7 +21,6 @@ module ActiveRelation
WHERE `users`.`id` = 1
""")
end
end
end
end

View file

@ -0,0 +1,70 @@
require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
module ActiveRelation
describe Session do
before do
@relation = Table.new(:users)
@session = Session.instance
end
describe Singleton do
it "is a singleton" do
Session.instance.should be_equal(Session.instance)
lambda { Session.new }.should raise_error
end
end
describe Session::CRUD do
before do
@insert = Insertion.new(@relation, @relation[:name] => 'nick')
@update = Update.new(@relation, @relation[:name] => 'nick')
@delete = Deletion.new(@relation)
@select = @relation
end
describe '#create' do
it "should execute an insertion on the connection" do
mock(@session.connection).insert(@insert.to_sql)
@session.create(@insert)
end
end
describe '#read' do
it "should execute an selection on the connection" do
mock(@session.connection).select_all(@select.to_sql)
@session.read(@select)
end
end
describe '#update' do
it "should execute an update on the connection" do
mock(@session.connection).update(@update.to_sql)
@session.update(@update)
end
end
describe '#delete' do
it "should execute a delete on the connection" do
mock(@session.connection).delete(@delete.to_sql)
@session.delete(@delete)
end
end
end
describe Session::Transactions do
describe '#begin' do
end
describe '#end' do
end
end
describe Session::UnitOfWork do
describe '#flush' do
end
describe '#clear' do
end
end
end
end

View file

@ -7,7 +7,7 @@ Dir["#{dir}/matchers/*"].each { |m| require "#{dir}/matchers/#{File.basename(m)}
require 'active_relation'
ActiveRecord::Base.configurations = {
'sql_algebra_test' => {
'test' => {
:adapter => 'mysql',
:username => 'root',
:password => 'password',
@ -15,7 +15,7 @@ ActiveRecord::Base.configurations = {
:database => 'sql_algebra_test',
},
}
ActiveRecord::Base.establish_connection 'sql_algebra_test'
ActiveRecord::Base.establish_connection 'test'
class Hash
def shift