aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eager include.txt49
-rw-r--r--lib/active_relation.rb56
-rw-r--r--lib/active_relation/extensions/array.rb (renamed from lib/sql_algebra/extensions/array.rb)0
-rw-r--r--lib/active_relation/extensions/base.rb (renamed from lib/sql_algebra/extensions/base.rb)0
-rw-r--r--lib/active_relation/extensions/hash.rb (renamed from lib/sql_algebra/extensions/hash.rb)6
-rw-r--r--lib/active_relation/extensions/object.rb (renamed from lib/sql_algebra/extensions/object.rb)0
-rw-r--r--lib/active_relation/extensions/range.rb (renamed from lib/sql_algebra/extensions/range.rb)0
-rw-r--r--lib/active_relation/predicates/binary_predicate.rb (renamed from lib/sql_algebra/predicates/binary_predicate.rb)0
-rw-r--r--lib/active_relation/predicates/equality_predicate.rb (renamed from lib/sql_algebra/predicates/equality_predicate.rb)0
-rw-r--r--lib/active_relation/predicates/greater_than_or_equal_to_predicate.rb (renamed from lib/sql_algebra/predicates/greater_than_or_equal_to_predicate.rb)0
-rw-r--r--lib/active_relation/predicates/greater_than_predicate.rb (renamed from lib/sql_algebra/predicates/greater_than_predicate.rb)0
-rw-r--r--lib/active_relation/predicates/less_than_or_equal_to_predicate.rb (renamed from lib/sql_algebra/predicates/less_than_or_equal_to_predicate.rb)0
-rw-r--r--lib/active_relation/predicates/less_than_predicate.rb (renamed from lib/sql_algebra/predicates/less_than_predicate.rb)0
-rw-r--r--lib/active_relation/predicates/match_predicate.rb (renamed from lib/sql_algebra/predicates/match_predicate.rb)0
-rw-r--r--lib/active_relation/predicates/predicate.rb (renamed from lib/sql_algebra/predicates/predicate.rb)0
-rw-r--r--lib/active_relation/predicates/range_inclusion_predicate.rb (renamed from lib/sql_algebra/predicates/range_inclusion_predicate.rb)0
-rw-r--r--lib/active_relation/predicates/relation_inclusion_predicate.rb (renamed from lib/sql_algebra/predicates/relation_inclusion_predicate.rb)0
-rw-r--r--lib/active_relation/relations/attribute.rb (renamed from lib/sql_algebra/relations/attribute.rb)0
-rw-r--r--lib/active_relation/relations/compound_relation.rb3
-rw-r--r--lib/active_relation/relations/deletion_relation.rb22
-rw-r--r--lib/active_relation/relations/inner_join_operation.rb (renamed from lib/sql_algebra/relations/inner_join_operation.rb)0
-rw-r--r--lib/active_relation/relations/inner_join_relation.rb (renamed from lib/sql_algebra/relations/inner_join_relation.rb)0
-rw-r--r--lib/active_relation/relations/insertion_relation.rb29
-rw-r--r--lib/active_relation/relations/join.rb (renamed from lib/sql_algebra/relations/join.rb)0
-rw-r--r--lib/active_relation/relations/join_operation.rb (renamed from lib/sql_algebra/relations/join_operation.rb)0
-rw-r--r--lib/active_relation/relations/join_relation.rb (renamed from lib/sql_algebra/relations/join_relation.rb)0
-rw-r--r--lib/active_relation/relations/left_outer_join_operation.rb (renamed from lib/sql_algebra/relations/left_outer_join_operation.rb)0
-rw-r--r--lib/active_relation/relations/left_outer_join_relation.rb (renamed from lib/sql_algebra/relations/left_outer_join_relation.rb)0
-rw-r--r--lib/active_relation/relations/order_relation.rb (renamed from lib/sql_algebra/relations/order_relation.rb)0
-rw-r--r--lib/active_relation/relations/projection_relation.rb (renamed from lib/sql_algebra/relations/projection_relation.rb)0
-rw-r--r--lib/active_relation/relations/range_relation.rb (renamed from lib/sql_algebra/relations/range_relation.rb)0
-rw-r--r--lib/active_relation/relations/relation.rb (renamed from lib/sql_algebra/relations/relation.rb)10
-rw-r--r--lib/active_relation/relations/rename_relation.rb (renamed from lib/sql_algebra/relations/rename_relation.rb)0
-rw-r--r--lib/active_relation/relations/selection_relation.rb (renamed from lib/sql_algebra/relations/selection_relation.rb)2
-rw-r--r--lib/active_relation/relations/table_relation.rb (renamed from lib/sql_algebra/relations/table_relation.rb)0
-rw-r--r--lib/active_relation/sql_builder/columns_builder.rb16
-rw-r--r--lib/active_relation/sql_builder/conditions_builder.rb (renamed from lib/sql_algebra/sql_builder/conditions_builder.rb)4
-rw-r--r--lib/active_relation/sql_builder/delete_builder.rb32
-rw-r--r--lib/active_relation/sql_builder/equals_condition_builder.rb (renamed from lib/sql_algebra/sql_builder/equals_condition_builder.rb)0
-rw-r--r--lib/active_relation/sql_builder/inner_join_builder.rb (renamed from lib/sql_algebra/sql_builder/inner_join_builder.rb)0
-rw-r--r--lib/active_relation/sql_builder/insert_builder.rb41
-rw-r--r--lib/active_relation/sql_builder/join_builder.rb (renamed from lib/sql_algebra/sql_builder/join_builder.rb)0
-rw-r--r--lib/active_relation/sql_builder/joins_builder.rb (renamed from lib/sql_algebra/sql_builder/joins_builder.rb)0
-rw-r--r--lib/active_relation/sql_builder/left_outer_join_builder.rb (renamed from lib/sql_algebra/sql_builder/left_outer_join_builder.rb)0
-rw-r--r--lib/active_relation/sql_builder/order_builder.rb (renamed from lib/sql_algebra/sql_builder/order_builder.rb)0
-rw-r--r--lib/active_relation/sql_builder/select_builder.rb (renamed from lib/sql_algebra/sql_builder/select_builder.rb)3
-rw-r--r--lib/active_relation/sql_builder/selects_builder.rb9
-rw-r--r--lib/active_relation/sql_builder/sql_builder.rb (renamed from lib/sql_algebra/sql_builder/sql_builder.rb)0
-rw-r--r--lib/active_relation/sql_builder/values_builder.rb16
-rw-r--r--lib/sql_algebra.rb49
-rw-r--r--lib/sql_algebra/relations/compound_relation.rb3
-rw-r--r--lib/sql_algebra/sql_builder/selects_builder.rb20
-rw-r--r--spec/active_relation/integration/scratch_spec.rb (renamed from spec/integration/scratch_spec.rb)87
-rw-r--r--spec/active_relation/predicates/binary_predicate_spec.rb (renamed from spec/predicates/binary_predicate_spec.rb)2
-rw-r--r--spec/active_relation/predicates/equality_predicate_spec.rb (renamed from spec/predicates/equality_predicate_spec.rb)2
-rw-r--r--spec/active_relation/predicates/relation_inclusion_predicate_spec.rb (renamed from spec/predicates/relation_inclusion_predicate_spec.rb)2
-rw-r--r--spec/active_relation/relations/attribute_spec.rb (renamed from spec/relations/attribute_spec.rb)2
-rw-r--r--spec/active_relation/relations/deletion_relation_spec.rb22
-rw-r--r--spec/active_relation/relations/insertion_relation_spec.rb37
-rw-r--r--spec/active_relation/relations/join_operation_spec.rb (renamed from spec/relations/join_operation_spec.rb)6
-rw-r--r--spec/active_relation/relations/join_relation_spec.rb (renamed from spec/relations/join_relation_spec.rb)2
-rw-r--r--spec/active_relation/relations/order_relation_spec.rb (renamed from spec/relations/order_relation_spec.rb)2
-rw-r--r--spec/active_relation/relations/projection_relation_spec.rb (renamed from spec/relations/projection_relation_spec.rb)2
-rw-r--r--spec/active_relation/relations/range_relation_spec.rb (renamed from spec/relations/range_relation_spec.rb)2
-rw-r--r--spec/active_relation/relations/relation_spec.rb92
-rw-r--r--spec/active_relation/relations/rename_relation_spec.rb (renamed from spec/relations/rename_relation_spec.rb)2
-rw-r--r--spec/active_relation/relations/selection_relation_spec.rb (renamed from spec/relations/selection_relation_spec.rb)2
-rw-r--r--spec/active_relation/relations/table_relation_spec.rb (renamed from spec/relations/table_relation_spec.rb)2
-rw-r--r--spec/active_relation/sql_builder/conditions_spec.rb (renamed from spec/sql_builder/conditions_spec.rb)2
-rw-r--r--spec/active_relation/sql_builder/delete_builder_spec.rb22
-rw-r--r--spec/active_relation/sql_builder/insert_builder_spec.rb24
-rw-r--r--spec/active_relation/sql_builder/select_builder_spec.rb (renamed from spec/sql_builder/select_builder_spec.rb)39
-rw-r--r--spec/debug.log1
-rw-r--r--spec/extensions/range_spec.rb1
-rw-r--r--spec/integration/debug.log0
-rw-r--r--spec/matchers/be_like.rb (renamed from spec/spec_helpers/be_like.rb)0
-rw-r--r--spec/relations/relation_spec.rb72
-rw-r--r--spec/spec_helper.rb7
78 files changed, 566 insertions, 238 deletions
diff --git a/eager include.txt b/eager include.txt
deleted file mode 100644
index 0c56323b40..0000000000
--- a/eager include.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-User.find( :all, :include => { :photos => :camera } )
-
-User.reflection[:photos].klass.reflection[:camera]
-
-users_photos_camera = User.relation << User.reflections[:photos].relation << Photo.reflections[:camera].relation
-
-users_photos_camera.each do |record|
- User.bring_forth(record, :photos => :camera)
-end
-
-def User.bring_forth(record, included = { :photos => :camera })
- user = @cache[ record % 'users.id' ] || User.instantiate(record % User.attributes)
- user.photos.bring_forth(record, :camera)
-end
-
-def User.photos.bring_forth(record, included = :camera)
- photo = @cache[ record % 'photos.id' ] || Photo.instantiate(record % Photo.attributes)
- photo.camera.bring_forth(record)
-end
-
-def User.photos.camera.bring_forth(record, included = nil)
- camera = @cache [ record % 'cameras.id' ] || Camera.instantiate(record % Camera.attributes)
-end
-
-###########################
-
-# first, rename the attributes to remove ambiguity (analogous to c0_t0 stuff)
-eager_loaded_user_cameras = @user_cameras.rename(
- @user.attributes => @user.attributes.prefixed,
- @photos.attributes => ...,
- @cameras.attributes => ...,
-)
-
-# second, bring forth!!
-class Repository
- def bring_forth(record, includes = [])
- object = cache.get(record % klass.primary_key) { Klass.instantiate(record % Klass.attributes) }
- includes.each do |include|
- case include
- when Symbol
- object.send(association = include).bring_forth(record)
- when Hash
- include.each do |association, nested_associations|
- object.send(association).bring_forth(record, nested_associations)
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/lib/active_relation.rb b/lib/active_relation.rb
new file mode 100644
index 0000000000..0d7af7bfb8
--- /dev/null
+++ b/lib/active_relation.rb
@@ -0,0 +1,56 @@
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+
+require 'rubygems'
+require 'activesupport'
+require 'activerecord'
+
+require 'active_relation/relations/relation'
+require 'active_relation/relations/compound_relation'
+require 'active_relation/relations/table_relation'
+require 'active_relation/relations/join_operation'
+require 'active_relation/relations/inner_join_operation'
+require 'active_relation/relations/left_outer_join_operation'
+require 'active_relation/relations/join_relation'
+require 'active_relation/relations/inner_join_relation'
+require 'active_relation/relations/left_outer_join_relation'
+require 'active_relation/relations/attribute'
+require 'active_relation/relations/projection_relation'
+require 'active_relation/relations/selection_relation'
+require 'active_relation/relations/order_relation'
+require 'active_relation/relations/range_relation'
+require 'active_relation/relations/rename_relation'
+require 'active_relation/relations/join'
+require 'active_relation/relations/deletion_relation'
+require 'active_relation/relations/insertion_relation'
+
+require 'active_relation/predicates/predicate'
+require 'active_relation/predicates/binary_predicate'
+require 'active_relation/predicates/equality_predicate'
+require 'active_relation/predicates/less_than_predicate'
+require 'active_relation/predicates/less_than_or_equal_to_predicate'
+require 'active_relation/predicates/greater_than_predicate'
+require 'active_relation/predicates/greater_than_or_equal_to_predicate'
+require 'active_relation/predicates/range_inclusion_predicate'
+require 'active_relation/predicates/relation_inclusion_predicate'
+require 'active_relation/predicates/match_predicate'
+
+require 'active_relation/extensions/range'
+require 'active_relation/extensions/object'
+require 'active_relation/extensions/array'
+require 'active_relation/extensions/base'
+require 'active_relation/extensions/hash'
+
+require 'active_relation/sql_builder/sql_builder'
+require 'active_relation/sql_builder/select_builder'
+require 'active_relation/sql_builder/delete_builder'
+require 'active_relation/sql_builder/insert_builder'
+require 'active_relation/sql_builder/joins_builder'
+require 'active_relation/sql_builder/join_builder'
+require 'active_relation/sql_builder/inner_join_builder'
+require 'active_relation/sql_builder/left_outer_join_builder'
+require 'active_relation/sql_builder/equals_condition_builder'
+require 'active_relation/sql_builder/conditions_builder'
+require 'active_relation/sql_builder/order_builder'
+require 'active_relation/sql_builder/columns_builder'
+require 'active_relation/sql_builder/selects_builder'
+require 'active_relation/sql_builder/values_builder' \ No newline at end of file
diff --git a/lib/sql_algebra/extensions/array.rb b/lib/active_relation/extensions/array.rb
index 5b6d6d6abd..5b6d6d6abd 100644
--- a/lib/sql_algebra/extensions/array.rb
+++ b/lib/active_relation/extensions/array.rb
diff --git a/lib/sql_algebra/extensions/base.rb b/lib/active_relation/extensions/base.rb
index 0dbdef703f..0dbdef703f 100644
--- a/lib/sql_algebra/extensions/base.rb
+++ b/lib/active_relation/extensions/base.rb
diff --git a/lib/sql_algebra/extensions/hash.rb b/lib/active_relation/extensions/hash.rb
index c83ee0d04f..f643ac17ab 100644
--- a/lib/sql_algebra/extensions/hash.rb
+++ b/lib/active_relation/extensions/hash.rb
@@ -4,4 +4,10 @@ class Hash
aliased.merge(yield(key) => value)
end
end
+
+ def to_sql(builder = ValuesBuilder.new)
+ builder.call do
+ row *values
+ end
+ end
end \ No newline at end of file
diff --git a/lib/sql_algebra/extensions/object.rb b/lib/active_relation/extensions/object.rb
index c241581f86..c241581f86 100644
--- a/lib/sql_algebra/extensions/object.rb
+++ b/lib/active_relation/extensions/object.rb
diff --git a/lib/sql_algebra/extensions/range.rb b/lib/active_relation/extensions/range.rb
index e69de29bb2..e69de29bb2 100644
--- a/lib/sql_algebra/extensions/range.rb
+++ b/lib/active_relation/extensions/range.rb
diff --git a/lib/sql_algebra/predicates/binary_predicate.rb b/lib/active_relation/predicates/binary_predicate.rb
index f5c420c833..f5c420c833 100644
--- a/lib/sql_algebra/predicates/binary_predicate.rb
+++ b/lib/active_relation/predicates/binary_predicate.rb
diff --git a/lib/sql_algebra/predicates/equality_predicate.rb b/lib/active_relation/predicates/equality_predicate.rb
index 7040c45f67..7040c45f67 100644
--- a/lib/sql_algebra/predicates/equality_predicate.rb
+++ b/lib/active_relation/predicates/equality_predicate.rb
diff --git a/lib/sql_algebra/predicates/greater_than_or_equal_to_predicate.rb b/lib/active_relation/predicates/greater_than_or_equal_to_predicate.rb
index 49127c312c..49127c312c 100644
--- a/lib/sql_algebra/predicates/greater_than_or_equal_to_predicate.rb
+++ b/lib/active_relation/predicates/greater_than_or_equal_to_predicate.rb
diff --git a/lib/sql_algebra/predicates/greater_than_predicate.rb b/lib/active_relation/predicates/greater_than_predicate.rb
index 03aecaed62..03aecaed62 100644
--- a/lib/sql_algebra/predicates/greater_than_predicate.rb
+++ b/lib/active_relation/predicates/greater_than_predicate.rb
diff --git a/lib/sql_algebra/predicates/less_than_or_equal_to_predicate.rb b/lib/active_relation/predicates/less_than_or_equal_to_predicate.rb
index fee6ea7f35..fee6ea7f35 100644
--- a/lib/sql_algebra/predicates/less_than_or_equal_to_predicate.rb
+++ b/lib/active_relation/predicates/less_than_or_equal_to_predicate.rb
diff --git a/lib/sql_algebra/predicates/less_than_predicate.rb b/lib/active_relation/predicates/less_than_predicate.rb
index 03cbdcf000..03cbdcf000 100644
--- a/lib/sql_algebra/predicates/less_than_predicate.rb
+++ b/lib/active_relation/predicates/less_than_predicate.rb
diff --git a/lib/sql_algebra/predicates/match_predicate.rb b/lib/active_relation/predicates/match_predicate.rb
index 90a13090d4..90a13090d4 100644
--- a/lib/sql_algebra/predicates/match_predicate.rb
+++ b/lib/active_relation/predicates/match_predicate.rb
diff --git a/lib/sql_algebra/predicates/predicate.rb b/lib/active_relation/predicates/predicate.rb
index 4c395a3fdc..4c395a3fdc 100644
--- a/lib/sql_algebra/predicates/predicate.rb
+++ b/lib/active_relation/predicates/predicate.rb
diff --git a/lib/sql_algebra/predicates/range_inclusion_predicate.rb b/lib/active_relation/predicates/range_inclusion_predicate.rb
index e69de29bb2..e69de29bb2 100644
--- a/lib/sql_algebra/predicates/range_inclusion_predicate.rb
+++ b/lib/active_relation/predicates/range_inclusion_predicate.rb
diff --git a/lib/sql_algebra/predicates/relation_inclusion_predicate.rb b/lib/active_relation/predicates/relation_inclusion_predicate.rb
index 5881a85d99..5881a85d99 100644
--- a/lib/sql_algebra/predicates/relation_inclusion_predicate.rb
+++ b/lib/active_relation/predicates/relation_inclusion_predicate.rb
diff --git a/lib/sql_algebra/relations/attribute.rb b/lib/active_relation/relations/attribute.rb
index 7583553b80..7583553b80 100644
--- a/lib/sql_algebra/relations/attribute.rb
+++ b/lib/active_relation/relations/attribute.rb
diff --git a/lib/active_relation/relations/compound_relation.rb b/lib/active_relation/relations/compound_relation.rb
new file mode 100644
index 0000000000..fe92905d92
--- /dev/null
+++ b/lib/active_relation/relations/compound_relation.rb
@@ -0,0 +1,3 @@
+class CompoundRelation < Relation
+ delegate :attributes, :attribute, :joins, :selects, :orders, :table, :inserts, :to => :relation
+end \ No newline at end of file
diff --git a/lib/active_relation/relations/deletion_relation.rb b/lib/active_relation/relations/deletion_relation.rb
new file mode 100644
index 0000000000..e060efd5f9
--- /dev/null
+++ b/lib/active_relation/relations/deletion_relation.rb
@@ -0,0 +1,22 @@
+class DeletionRelation < CompoundRelation
+ attr_reader :relation
+
+ def ==(other)
+ relation == other.relation
+ end
+
+ def initialize(relation)
+ @relation = relation
+ end
+
+ def to_sql(builder = DeleteBuilder.new)
+ builder.call do
+ delete
+ from table
+ where do
+ selects.each { |s| s.to_sql(self) }
+ end
+ end
+ end
+
+end \ No newline at end of file
diff --git a/lib/sql_algebra/relations/inner_join_operation.rb b/lib/active_relation/relations/inner_join_operation.rb
index 6b5c5ce8d0..6b5c5ce8d0 100644
--- a/lib/sql_algebra/relations/inner_join_operation.rb
+++ b/lib/active_relation/relations/inner_join_operation.rb
diff --git a/lib/sql_algebra/relations/inner_join_relation.rb b/lib/active_relation/relations/inner_join_relation.rb
index 5e58f241f8..5e58f241f8 100644
--- a/lib/sql_algebra/relations/inner_join_relation.rb
+++ b/lib/active_relation/relations/inner_join_relation.rb
diff --git a/lib/active_relation/relations/insertion_relation.rb b/lib/active_relation/relations/insertion_relation.rb
new file mode 100644
index 0000000000..84752d13f9
--- /dev/null
+++ b/lib/active_relation/relations/insertion_relation.rb
@@ -0,0 +1,29 @@
+class InsertionRelation < CompoundRelation
+ attr_reader :relation, :tuple
+
+ def initialize(relation, tuple)
+ @relation, @tuple = relation, tuple
+ end
+
+ def to_sql(builder = InsertBuilder.new)
+ builder.call do
+ insert
+ into table
+ columns do
+ tuple.keys.each { |attribute| attribute.to_sql(self) }
+ end
+ values do
+ inserts.each { |insert| insert.to_sql(self) }
+ end
+ end
+ end
+
+ def ==(other)
+ relation == other.relation and tuple == other.tuple
+ end
+
+ protected
+ def inserts
+ relation.inserts + [tuple]
+ end
+end \ No newline at end of file
diff --git a/lib/sql_algebra/relations/join.rb b/lib/active_relation/relations/join.rb
index 9a6196deac..9a6196deac 100644
--- a/lib/sql_algebra/relations/join.rb
+++ b/lib/active_relation/relations/join.rb
diff --git a/lib/sql_algebra/relations/join_operation.rb b/lib/active_relation/relations/join_operation.rb
index 2b4548a041..2b4548a041 100644
--- a/lib/sql_algebra/relations/join_operation.rb
+++ b/lib/active_relation/relations/join_operation.rb
diff --git a/lib/sql_algebra/relations/join_relation.rb b/lib/active_relation/relations/join_relation.rb
index 79c8a915b8..79c8a915b8 100644
--- a/lib/sql_algebra/relations/join_relation.rb
+++ b/lib/active_relation/relations/join_relation.rb
diff --git a/lib/sql_algebra/relations/left_outer_join_operation.rb b/lib/active_relation/relations/left_outer_join_operation.rb
index fbb2a4e2ed..fbb2a4e2ed 100644
--- a/lib/sql_algebra/relations/left_outer_join_operation.rb
+++ b/lib/active_relation/relations/left_outer_join_operation.rb
diff --git a/lib/sql_algebra/relations/left_outer_join_relation.rb b/lib/active_relation/relations/left_outer_join_relation.rb
index 6d13d8da07..6d13d8da07 100644
--- a/lib/sql_algebra/relations/left_outer_join_relation.rb
+++ b/lib/active_relation/relations/left_outer_join_relation.rb
diff --git a/lib/sql_algebra/relations/order_relation.rb b/lib/active_relation/relations/order_relation.rb
index b39dc45c3f..b39dc45c3f 100644
--- a/lib/sql_algebra/relations/order_relation.rb
+++ b/lib/active_relation/relations/order_relation.rb
diff --git a/lib/sql_algebra/relations/projection_relation.rb b/lib/active_relation/relations/projection_relation.rb
index 1a0e8dbfe4..1a0e8dbfe4 100644
--- a/lib/sql_algebra/relations/projection_relation.rb
+++ b/lib/active_relation/relations/projection_relation.rb
diff --git a/lib/sql_algebra/relations/range_relation.rb b/lib/active_relation/relations/range_relation.rb
index 9225d5615b..9225d5615b 100644
--- a/lib/sql_algebra/relations/range_relation.rb
+++ b/lib/active_relation/relations/range_relation.rb
diff --git a/lib/sql_algebra/relations/relation.rb b/lib/active_relation/relations/relation.rb
index 8efe0c7d9f..be6ee760a5 100644
--- a/lib/sql_algebra/relations/relation.rb
+++ b/lib/active_relation/relations/relation.rb
@@ -49,6 +49,14 @@ class Relation
def rename(attribute, aliaz)
RenameRelation.new(self, attribute => aliaz)
end
+
+ def insert(tuple)
+ InsertionRelation.new(self, tuple)
+ end
+
+ def delete
+ DeletionRelation.new(self)
+ end
end
include Operations
@@ -79,5 +87,5 @@ class Relation
def joins; [] end
def selects; [] end
def orders; [] end
-
+ def inserts; [] end
end \ No newline at end of file
diff --git a/lib/sql_algebra/relations/rename_relation.rb b/lib/active_relation/relations/rename_relation.rb
index 8acf5091b2..8acf5091b2 100644
--- a/lib/sql_algebra/relations/rename_relation.rb
+++ b/lib/active_relation/relations/rename_relation.rb
diff --git a/lib/sql_algebra/relations/selection_relation.rb b/lib/active_relation/relations/selection_relation.rb
index dcf5f4745f..77864efb28 100644
--- a/lib/sql_algebra/relations/selection_relation.rb
+++ b/lib/active_relation/relations/selection_relation.rb
@@ -16,6 +16,6 @@ class SelectionRelation < CompoundRelation
protected
def selects
- [predicate]
+ relation.send(:selects) + [predicate]
end
end \ No newline at end of file
diff --git a/lib/sql_algebra/relations/table_relation.rb b/lib/active_relation/relations/table_relation.rb
index 5a47ae7a34..5a47ae7a34 100644
--- a/lib/sql_algebra/relations/table_relation.rb
+++ b/lib/active_relation/relations/table_relation.rb
diff --git a/lib/active_relation/sql_builder/columns_builder.rb b/lib/active_relation/sql_builder/columns_builder.rb
new file mode 100644
index 0000000000..a8a5d0e4ca
--- /dev/null
+++ b/lib/active_relation/sql_builder/columns_builder.rb
@@ -0,0 +1,16 @@
+class ColumnsBuilder < SqlBuilder
+ def initialize(&block)
+ @columns = []
+ super(&block)
+ end
+
+ def to_s
+ @columns.join(', ')
+ end
+
+ def column(table, column, aliaz = nil)
+ @columns << "#{quote_table_name(table)}.#{quote_column_name(column)}"
+ end
+
+ delegate :blank?, :to => :@columns
+end \ No newline at end of file
diff --git a/lib/sql_algebra/sql_builder/conditions_builder.rb b/lib/active_relation/sql_builder/conditions_builder.rb
index 5d42a36cec..60430f65d8 100644
--- a/lib/sql_algebra/sql_builder/conditions_builder.rb
+++ b/lib/active_relation/sql_builder/conditions_builder.rb
@@ -7,6 +7,10 @@ class ConditionsBuilder < SqlBuilder
def equals(&block)
@conditions << EqualsConditionBuilder.new(&block)
end
+
+ def value(value)
+ @conditions << value
+ end
def to_s
@conditions.join(' AND ')
diff --git a/lib/active_relation/sql_builder/delete_builder.rb b/lib/active_relation/sql_builder/delete_builder.rb
new file mode 100644
index 0000000000..2e8be94dfe
--- /dev/null
+++ b/lib/active_relation/sql_builder/delete_builder.rb
@@ -0,0 +1,32 @@
+class DeleteBuilder < SqlBuilder
+ def delete
+ end
+
+ def from(table)
+ @table = table
+ end
+
+ def where(&block)
+ @conditions = ConditionsBuilder.new(&block)
+ end
+
+ def to_s
+ [delete_clause,
+ from_clause,
+ where_clause
+ ].compact.join("\n")
+ end
+
+ private
+ def delete_clause
+ "DELETE"
+ end
+
+ def from_clause
+ "FROM #{quote_table_name(@table)}"
+ end
+
+ def where_clause
+ "WHERE #{@conditions}" unless @conditions.blank?
+ end
+end \ No newline at end of file
diff --git a/lib/sql_algebra/sql_builder/equals_condition_builder.rb b/lib/active_relation/sql_builder/equals_condition_builder.rb
index cfa919c34c..cfa919c34c 100644
--- a/lib/sql_algebra/sql_builder/equals_condition_builder.rb
+++ b/lib/active_relation/sql_builder/equals_condition_builder.rb
diff --git a/lib/sql_algebra/sql_builder/inner_join_builder.rb b/lib/active_relation/sql_builder/inner_join_builder.rb
index 6aec703325..6aec703325 100644
--- a/lib/sql_algebra/sql_builder/inner_join_builder.rb
+++ b/lib/active_relation/sql_builder/inner_join_builder.rb
diff --git a/lib/active_relation/sql_builder/insert_builder.rb b/lib/active_relation/sql_builder/insert_builder.rb
new file mode 100644
index 0000000000..09deefad10
--- /dev/null
+++ b/lib/active_relation/sql_builder/insert_builder.rb
@@ -0,0 +1,41 @@
+class InsertBuilder < SqlBuilder
+ def insert
+ end
+
+ def into(table)
+ @table = table
+ end
+
+ def columns(&block)
+ @columns = ColumnsBuilder.new(&block)
+ end
+
+ def values(&block)
+ @values = ValuesBuilder.new(&block)
+ end
+
+ def to_s
+ [insert_clause,
+ into_clause,
+ columns_clause,
+ values_clause
+ ].compact.join("\n")
+ end
+
+ private
+ def insert_clause
+ "INSERT"
+ end
+
+ def into_clause
+ "INTO #{quote_table_name(@table)}"
+ end
+
+ def values_clause
+ "VALUES #{@values}" unless @values.blank?
+ end
+
+ def columns_clause
+ "(#{@columns})" unless @columns.blank?
+ end
+end \ No newline at end of file
diff --git a/lib/sql_algebra/sql_builder/join_builder.rb b/lib/active_relation/sql_builder/join_builder.rb
index ef63d1fcb1..ef63d1fcb1 100644
--- a/lib/sql_algebra/sql_builder/join_builder.rb
+++ b/lib/active_relation/sql_builder/join_builder.rb
diff --git a/lib/sql_algebra/sql_builder/joins_builder.rb b/lib/active_relation/sql_builder/joins_builder.rb
index 36a92e9922..36a92e9922 100644
--- a/lib/sql_algebra/sql_builder/joins_builder.rb
+++ b/lib/active_relation/sql_builder/joins_builder.rb
diff --git a/lib/sql_algebra/sql_builder/left_outer_join_builder.rb b/lib/active_relation/sql_builder/left_outer_join_builder.rb
index dad3f85810..dad3f85810 100644
--- a/lib/sql_algebra/sql_builder/left_outer_join_builder.rb
+++ b/lib/active_relation/sql_builder/left_outer_join_builder.rb
diff --git a/lib/sql_algebra/sql_builder/order_builder.rb b/lib/active_relation/sql_builder/order_builder.rb
index 66a8cfdba9..66a8cfdba9 100644
--- a/lib/sql_algebra/sql_builder/order_builder.rb
+++ b/lib/active_relation/sql_builder/order_builder.rb
diff --git a/lib/sql_algebra/sql_builder/select_builder.rb b/lib/active_relation/sql_builder/select_builder.rb
index 9a85ad7eec..57116cb64b 100644
--- a/lib/sql_algebra/sql_builder/select_builder.rb
+++ b/lib/active_relation/sql_builder/select_builder.rb
@@ -9,8 +9,7 @@ class SelectBuilder < SqlBuilder
end
def where(&block)
- @conditions ||= ConditionsBuilder.new
- @conditions.call(&block)
+ @conditions = ConditionsBuilder.new(&block)
end
def order_by(&block)
diff --git a/lib/active_relation/sql_builder/selects_builder.rb b/lib/active_relation/sql_builder/selects_builder.rb
new file mode 100644
index 0000000000..6ad06d0ae4
--- /dev/null
+++ b/lib/active_relation/sql_builder/selects_builder.rb
@@ -0,0 +1,9 @@
+class SelectsBuilder < ColumnsBuilder
+ def all
+ @columns << :*
+ end
+
+ def column(table, column, aliaz = nil)
+ @columns << "#{quote_table_name(table)}.#{quote_column_name(column)}" + (aliaz ? " AS #{quote(aliaz)}" : '')
+ end
+end \ No newline at end of file
diff --git a/lib/sql_algebra/sql_builder/sql_builder.rb b/lib/active_relation/sql_builder/sql_builder.rb
index c984444e41..c984444e41 100644
--- a/lib/sql_algebra/sql_builder/sql_builder.rb
+++ b/lib/active_relation/sql_builder/sql_builder.rb
diff --git a/lib/active_relation/sql_builder/values_builder.rb b/lib/active_relation/sql_builder/values_builder.rb
new file mode 100644
index 0000000000..f22b1e507e
--- /dev/null
+++ b/lib/active_relation/sql_builder/values_builder.rb
@@ -0,0 +1,16 @@
+class ValuesBuilder < SqlBuilder
+ def initialize(&block)
+ @values = []
+ super(&block)
+ end
+
+ def row(*values)
+ @values << "(#{values.collect { |v| quote(v) }.join(', ')})"
+ end
+
+ def to_s
+ @values.join(', ')
+ end
+
+ delegate :blank?, :to => :@values
+end \ No newline at end of file
diff --git a/lib/sql_algebra.rb b/lib/sql_algebra.rb
deleted file mode 100644
index fbd053541c..0000000000
--- a/lib/sql_algebra.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-$LOAD_PATH.unshift(File.dirname(__FILE__))
-require 'rubygems'
-require 'activesupport'
-require 'activerecord'
-
-require 'sql_algebra/relations/relation'
-require 'sql_algebra/relations/compound_relation'
-require 'sql_algebra/relations/table_relation'
-require 'sql_algebra/relations/join_operation'
-require 'sql_algebra/relations/inner_join_operation'
-require 'sql_algebra/relations/left_outer_join_operation'
-require 'sql_algebra/relations/join_relation'
-require 'sql_algebra/relations/inner_join_relation'
-require 'sql_algebra/relations/left_outer_join_relation'
-require 'sql_algebra/relations/attribute'
-require 'sql_algebra/relations/projection_relation'
-require 'sql_algebra/relations/selection_relation'
-require 'sql_algebra/relations/order_relation'
-require 'sql_algebra/relations/range_relation'
-require 'sql_algebra/relations/rename_relation'
-require 'sql_algebra/relations/join'
-
-require 'sql_algebra/predicates/predicate'
-require 'sql_algebra/predicates/binary_predicate'
-require 'sql_algebra/predicates/equality_predicate'
-require 'sql_algebra/predicates/less_than_predicate'
-require 'sql_algebra/predicates/less_than_or_equal_to_predicate'
-require 'sql_algebra/predicates/greater_than_predicate'
-require 'sql_algebra/predicates/greater_than_or_equal_to_predicate'
-require 'sql_algebra/predicates/range_inclusion_predicate'
-require 'sql_algebra/predicates/relation_inclusion_predicate'
-require 'sql_algebra/predicates/match_predicate'
-
-require 'sql_algebra/extensions/range'
-require 'sql_algebra/extensions/object'
-require 'sql_algebra/extensions/array'
-require 'sql_algebra/extensions/base'
-require 'sql_algebra/extensions/hash'
-
-require 'sql_algebra/sql_builder/sql_builder'
-require 'sql_algebra/sql_builder/select_builder'
-require 'sql_algebra/sql_builder/joins_builder'
-require 'sql_algebra/sql_builder/join_builder'
-require 'sql_algebra/sql_builder/inner_join_builder'
-require 'sql_algebra/sql_builder/left_outer_join_builder'
-require 'sql_algebra/sql_builder/equals_condition_builder'
-require 'sql_algebra/sql_builder/conditions_builder'
-require 'sql_algebra/sql_builder/order_builder'
-require 'sql_algebra/sql_builder/selects_builder' \ No newline at end of file
diff --git a/lib/sql_algebra/relations/compound_relation.rb b/lib/sql_algebra/relations/compound_relation.rb
deleted file mode 100644
index a8e9a41b5e..0000000000
--- a/lib/sql_algebra/relations/compound_relation.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class CompoundRelation < Relation
- delegate :attributes, :attribute, :joins, :select, :orders, :table, :to => :relation
-end \ No newline at end of file
diff --git a/lib/sql_algebra/sql_builder/selects_builder.rb b/lib/sql_algebra/sql_builder/selects_builder.rb
deleted file mode 100644
index ce6ee1eb67..0000000000
--- a/lib/sql_algebra/sql_builder/selects_builder.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-class SelectsBuilder < SqlBuilder
- def initialize(&block)
- @selects = []
- super(&block)
- end
-
- def to_s
- @selects.join(', ')
- end
-
- def all
- @selects << :*
- end
-
- def column(table, column, aliaz = nil)
- @selects << "#{quote_table_name(table)}.#{quote_column_name(column)}" + (aliaz ? " AS #{quote(aliaz)}" : '')
- end
-
- delegate :blank?, :to => :@selects
-end \ No newline at end of file
diff --git a/spec/integration/scratch_spec.rb b/spec/active_relation/integration/scratch_spec.rb
index b5d27f1dc2..fba587e4ba 100644
--- a/spec/integration/scratch_spec.rb
+++ b/spec/active_relation/integration/scratch_spec.rb
@@ -1,16 +1,16 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
-describe 'ActiveRelation', 'Proposed refactoring to ActiveRecord, introducing both a SQL
- builder and a Relational Algebra to mediate connections
- between ActiveRecord and the database. The goal of the
- refactoring is to remove code duplication concerning AR
- associations; remove complexity surrounding eager loading;
- comprehensively solve quoting issues; remove the with_scope
- merging logic; minimize the need for with_scope in general;
- simplify the implementation of plugins like HasFinder and
- ActsAsParanoid; introduce an identity map; and allow for
- query optimization. All this while effectively not changing
- the public interface of ActiveRecord.
+describe 'ActiveRelation', 'A proposed refactoring to ActiveRecord, introducing both a SQL
+ Builder and a Relational Algebra to mediate between
+ ActiveRecord and the database. The goal of the refactoring is
+ to remove code duplication concerning AR associations; remove
+ complexity surrounding eager loading; comprehensively solve
+ quoting issues; remove the with_scope merging logic; minimize
+ the need for with_scope in general; simplify the
+ implementation of plugins like HasFinder and ActsAsParanoid;
+ introduce an identity map; and allow for query optimization.
+ All this while remaining backwards-compatible with the
+ existing ActiveRecord interface.
The Relational Algebra makes these ambitious goals
possible. There\'s no need to be scared by the math, it\'s
actually quite simple. Relational Algebras have some nice
@@ -25,7 +25,7 @@ describe 'ActiveRelation', 'Proposed refactoring to ActiveRecord, introducing bo
should all be understood as \'Repositories\': a factory that
given a relation can manufacture objects, and given an object
can manipulate a relation. This may sound trivial, but I
- think it has the potential to make the code much smaller and
+ think it has the potential to make the code smaller and
more consistent.' do
before do
class User < ActiveRecord::Base; has_many :photos end
@@ -40,8 +40,8 @@ describe 'ActiveRelation', 'Proposed refactoring to ActiveRecord, introducing bo
@photos = Photo.relation
@cameras = Camera.relation
# A first taste of a Relational Algebra: User.find(1)
- # == is overridden on attributes to return a predicate, not true or false
@user = @users.select(@users[:id] == 1)
+ # == is overridden on attributes to return a predicate, not true or false
end
# In a Relational Algebra, the various ActiveRecord associations become a simple
@@ -122,13 +122,47 @@ describe 'ActiveRelation', 'Proposed refactoring to ActiveRecord, introducing bo
ON `photos`.`camera_id` = `cameras`.`id`
""")
end
+
+ it 'allows arbitrary sql to be passed through' do
+ (@users << @photos).on("asdf").to_s.should be_like("""
+ SELECT `users`.`name`, `users`.`id`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
+ FROM `users`
+ LEFT OUTER JOIN `photos`
+ ON asdf
+ """)
+ @users.select("asdf").to_s.should be_like("""
+ SELECT `users`.`name`, `users`.`id`
+ FROM `users`
+ WHERE asdf
+ """)
+ end
+
+ describe 'write operations' do
+ it 'generates the query for user.destroy' do
+ @user.delete.to_s.should be_like("""
+ DELETE
+ FROM `users`
+ WHERE `users`.`id` = 1
+ """)
+ end
- it 'obviates the need for with_scope merging logic since, e.g.,
- `with_scope :conditions => ...` is just a #select operation on the relation' do
+ it 'generates an efficient query for two User.creates -- UnitOfWork is within reach!' do
+ @users.insert(@users[:name] => "humpty").insert(@users[:name] => "dumpty").to_s.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
+ end
- it 'may eliminate the need for with_scope altogether since the associations no longer
- need it: the relation underlying the association fully encapsulates the scope' do
+ it 'may eliminate the need for with_scope altogether since the associations no longer
+ need it: the relation underlying the association fully encapsulates the scope' do
+ end
end
end
@@ -159,10 +193,11 @@ describe 'ActiveRelation', 'Proposed refactoring to ActiveRecord, introducing bo
describe 'the n+1 problem' do
describe 'the eager join algorithm is vastly simpler' do
- it 'three active records are loaded with only one query' do
+ it 'loads three active records with only one query' do
# using 'rr' mocking framework: the real #select_all is called, but we assert
# that it only happens once:
mock.proxy(ActiveRecord::Base.connection).select_all.with_any_args.once
+
users_cameras = photo_belongs_to_camera(user_has_many_photos(@users)).qualify
user = User.instantiate(users_cameras.first, [:photos => [:camera]])
user.photos.first.camera.attributes.should == {"id" => 1}
@@ -216,11 +251,21 @@ describe 'ActiveRelation', 'Proposed refactoring to ActiveRecord, introducing bo
photos for all subsequent users. This is substantially easier with the
Algebra since we can do @user.join(@photos).on(...) and transform that to
@users.join(@photos).on(...), relying on the IdentityMap to eliminate
- the n+1 problem. This is somewhat similar to ActiveRecordContext but it
- works with every association type, not just belongs_to." do
+ the n+1 problem." do
pending
end
end
end
end
+
+ describe 'The Architecture', 'I propose to produce a new gem, ActiveRelation, which encaplulates
+ the existing ActiveRecord Connection Adapter, the new SQL Builder,
+ and the Relational Algebra. ActiveRecord, then, should no longer
+ interact with the connection object directly.' do
+ end
+
+ describe 'Miscellaneous Ideas' do
+ it 'may be easy to write a SQL parser that can take arbitrary SQL and produce a relation.
+ This has the advantage of permitting e.g., pagination with custom finder_sql'
+ end
end \ No newline at end of file
diff --git a/spec/predicates/binary_predicate_spec.rb b/spec/active_relation/predicates/binary_predicate_spec.rb
index ede44e5175..5de559df41 100644
--- a/spec/predicates/binary_predicate_spec.rb
+++ b/spec/active_relation/predicates/binary_predicate_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe BinaryPredicate do
before do
diff --git a/spec/predicates/equality_predicate_spec.rb b/spec/active_relation/predicates/equality_predicate_spec.rb
index 75b495b6f7..af43b754e0 100644
--- a/spec/predicates/equality_predicate_spec.rb
+++ b/spec/active_relation/predicates/equality_predicate_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe EqualityPredicate do
before do
diff --git a/spec/predicates/relation_inclusion_predicate_spec.rb b/spec/active_relation/predicates/relation_inclusion_predicate_spec.rb
index 6cd37fafa8..f8c911429b 100644
--- a/spec/predicates/relation_inclusion_predicate_spec.rb
+++ b/spec/active_relation/predicates/relation_inclusion_predicate_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe RelationInclusionPredicate do
before do
diff --git a/spec/relations/attribute_spec.rb b/spec/active_relation/relations/attribute_spec.rb
index 4887be38d2..ddfc22fe28 100644
--- a/spec/relations/attribute_spec.rb
+++ b/spec/active_relation/relations/attribute_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe Attribute do
before do
diff --git a/spec/active_relation/relations/deletion_relation_spec.rb b/spec/active_relation/relations/deletion_relation_spec.rb
new file mode 100644
index 0000000000..4f75a261f4
--- /dev/null
+++ b/spec/active_relation/relations/deletion_relation_spec.rb
@@ -0,0 +1,22 @@
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
+
+describe DeletionRelation do
+ before do
+ @relation = TableRelation.new(:users)
+ end
+
+ describe '#to_sql' do
+ it 'manufactures sql deleting the relation' do
+ DeletionRelation.new(@relation.select(@relation[:id] == 1)).to_sql.to_s.should == DeleteBuilder.new do
+ delete
+ from :users
+ where do
+ equals do
+ column :users, :id
+ value 1
+ end
+ end
+ end.to_s
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/active_relation/relations/insertion_relation_spec.rb b/spec/active_relation/relations/insertion_relation_spec.rb
new file mode 100644
index 0000000000..6bafabb473
--- /dev/null
+++ b/spec/active_relation/relations/insertion_relation_spec.rb
@@ -0,0 +1,37 @@
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
+
+describe InsertionRelation do
+ before do
+ @relation = TableRelation.new(:users)
+ end
+
+ describe '#to_sql' do
+ it 'manufactures sql inserting the data for one item' do
+ InsertionRelation.new(@relation, @relation[:name] => "nick").to_sql.should == InsertBuilder.new do
+ insert
+ into :users
+ columns do
+ column :users, :name
+ end
+ values do
+ row "nick"
+ end
+ end
+ end
+
+ it 'manufactures sql inserting the data for multiple items' do
+ nested_insertion = InsertionRelation.new(@relation, @relation[:name] => "cobra")
+ InsertionRelation.new(nested_insertion, nested_insertion[:name] => "commander").to_sql.to_s.should == InsertBuilder.new do
+ insert
+ into :users
+ columns do
+ column :users, :name
+ end
+ values do
+ row "cobra"
+ row "commander"
+ end
+ end.to_s
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/relations/join_operation_spec.rb b/spec/active_relation/relations/join_operation_spec.rb
index db30198f6e..a8ab85123b 100644
--- a/spec/relations/join_operation_spec.rb
+++ b/spec/active_relation/relations/join_operation_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe 'between two relations' do
before do
@@ -31,5 +31,9 @@ describe 'between two relations' do
it "manufactures a join relation of the appropriate type" do
@join_operation.on(@predicate).should == JoinRelation.new(@relation1, @relation2, @predicate)
end
+
+ it "accepts arbitrary strings" do
+ @join_operation.on("arbitrary").should == JoinRelation.new(@relation1, @relation2, "arbitrary")
+ end
end
end \ No newline at end of file
diff --git a/spec/relations/join_relation_spec.rb b/spec/active_relation/relations/join_relation_spec.rb
index ece7e61cc1..d0be270837 100644
--- a/spec/relations/join_relation_spec.rb
+++ b/spec/active_relation/relations/join_relation_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe JoinRelation do
before do
diff --git a/spec/relations/order_relation_spec.rb b/spec/active_relation/relations/order_relation_spec.rb
index a78ac148e2..17f730b564 100644
--- a/spec/relations/order_relation_spec.rb
+++ b/spec/active_relation/relations/order_relation_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe OrderRelation do
before do
diff --git a/spec/relations/projection_relation_spec.rb b/spec/active_relation/relations/projection_relation_spec.rb
index 5a33b16bd5..164c485761 100644
--- a/spec/relations/projection_relation_spec.rb
+++ b/spec/active_relation/relations/projection_relation_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe ProjectionRelation do
before do
diff --git a/spec/relations/range_relation_spec.rb b/spec/active_relation/relations/range_relation_spec.rb
index 926cc0929f..ac9f887d9b 100644
--- a/spec/relations/range_relation_spec.rb
+++ b/spec/active_relation/relations/range_relation_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe RangeRelation do
before do
diff --git a/spec/active_relation/relations/relation_spec.rb b/spec/active_relation/relations/relation_spec.rb
new file mode 100644
index 0000000000..9ed42a98cb
--- /dev/null
+++ b/spec/active_relation/relations/relation_spec.rb
@@ -0,0 +1,92 @@
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
+
+describe Relation do
+ before do
+ @relation1 = TableRelation.new(:foo)
+ @relation2 = TableRelation.new(:bar)
+ @attribute1 = Attribute.new(@relation1, :id)
+ @attribute2 = Attribute.new(@relation1, :name)
+ end
+
+ describe '[]' do
+ it "manufactures an attribute when given a symbol" do
+ @relation1[:id].should be_eql(Attribute.new(@relation1, :id))
+ end
+
+ it "manufactures a range relation when given a range" do
+ @relation1[1..2].should == RangeRelation.new(@relation1, 1..2)
+ end
+ end
+
+ describe '#include?' do
+ it "manufactures an inclusion predicate" do
+ @relation1.include?(@attribute1).should == RelationInclusionPredicate.new(@attribute1, @relation1)
+ end
+ end
+
+ describe 'read operations' do
+ describe 'joins' do
+ describe '<=>' do
+ it "manufactures an inner join operation between those two relations" do
+ (@relation1 <=> @relation2).should == InnerJoinOperation.new(@relation1, @relation2)
+ end
+ end
+
+ describe '<<' do
+ it "manufactures a left outer join operation between those two relations" do
+ (@relation1 << @relation2).should == LeftOuterJoinOperation.new(@relation1, @relation2)
+ end
+ end
+ end
+
+ describe '#project' do
+ it "collapses identical projections" do
+ pending
+ end
+
+ it "manufactures a projection relation" do
+ @relation1.project(@attribute1, @attribute2).should == ProjectionRelation.new(@relation1, @attribute1, @attribute2)
+ end
+ end
+
+ describe '#rename' do
+ it "manufactures a rename relation" do
+ @relation1.rename(@attribute1, :foo).should == RenameRelation.new(@relation1, @attribute1 => :foo)
+ end
+ end
+
+ describe '#select' do
+ before do
+ @predicate = EqualityPredicate.new(@attribute1, @attribute2)
+ end
+
+ it "manufactures a selection relation" do
+ @relation1.select(@predicate).should == SelectionRelation.new(@relation1, @predicate)
+ end
+
+ it "accepts arbitrary strings" do
+ @relation1.select("arbitrary").should == SelectionRelation.new(@relation1, "arbitrary")
+ end
+ end
+
+ describe '#order' do
+ it "manufactures an order relation" do
+ @relation1.order(@attribute1, @attribute2).should == OrderRelation.new(@relation1, @attribute1, @attribute2)
+ end
+ end
+ end
+
+ describe 'write operations' do
+ describe '#delete' do
+ it 'manufactures a deletion relation' do
+ @relation1.delete.should == DeletionRelation.new(@relation1)
+ end
+ end
+
+ describe '#insert' do
+ it 'manufactures an insertion relation' do
+ @relation1.insert(tuple = {:id => 1}).should == InsertionRelation.new(@relation1, tuple)
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/relations/rename_relation_spec.rb b/spec/active_relation/relations/rename_relation_spec.rb
index 301ee6db9e..9b1d2d5cc8 100644
--- a/spec/relations/rename_relation_spec.rb
+++ b/spec/active_relation/relations/rename_relation_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe RenameRelation do
before do
diff --git a/spec/relations/selection_relation_spec.rb b/spec/active_relation/relations/selection_relation_spec.rb
index 656a386fd6..c4aadc807b 100644
--- a/spec/relations/selection_relation_spec.rb
+++ b/spec/active_relation/relations/selection_relation_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe SelectionRelation do
before do
diff --git a/spec/relations/table_relation_spec.rb b/spec/active_relation/relations/table_relation_spec.rb
index 0380372344..c943fe6c92 100644
--- a/spec/relations/table_relation_spec.rb
+++ b/spec/active_relation/relations/table_relation_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe TableRelation do
before do
diff --git a/spec/sql_builder/conditions_spec.rb b/spec/active_relation/sql_builder/conditions_spec.rb
index dc44cedc85..dc2d10a2f6 100644
--- a/spec/sql_builder/conditions_spec.rb
+++ b/spec/active_relation/sql_builder/conditions_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe ConditionsBuilder do
describe '#to_s' do
diff --git a/spec/active_relation/sql_builder/delete_builder_spec.rb b/spec/active_relation/sql_builder/delete_builder_spec.rb
new file mode 100644
index 0000000000..fd62fde155
--- /dev/null
+++ b/spec/active_relation/sql_builder/delete_builder_spec.rb
@@ -0,0 +1,22 @@
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
+
+describe DeleteBuilder do
+ describe '#to_s' do
+ it 'manufactures correct sql' do
+ DeleteBuilder.new do
+ delete
+ from :users
+ where do
+ equals do
+ column :users, :id
+ value 1
+ end
+ end
+ end.to_s.should be_like("""
+ DELETE
+ FROM `users`
+ WHERE `users`.`id` = 1
+ """)
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/active_relation/sql_builder/insert_builder_spec.rb b/spec/active_relation/sql_builder/insert_builder_spec.rb
new file mode 100644
index 0000000000..dddc971986
--- /dev/null
+++ b/spec/active_relation/sql_builder/insert_builder_spec.rb
@@ -0,0 +1,24 @@
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
+
+describe InsertBuilder do
+ describe '#to_s' do
+ it 'manufactures correct sql' do
+ InsertBuilder.new do
+ insert
+ into :users
+ columns do
+ column :users, :id
+ column :users, :name
+ end
+ values do
+ row 1, 'bob'
+ row 2, 'moe'
+ end
+ end.to_s.should be_like("""
+ INSERT
+ INTO `users`
+ (`users`.`id`, `users`.`name`) VALUES (1, 'bob'), (2, 'moe')
+ """)
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/sql_builder/select_builder_spec.rb b/spec/active_relation/sql_builder/select_builder_spec.rb
index 122539967e..6539afe0c4 100644
--- a/spec/sql_builder/select_builder_spec.rb
+++ b/spec/active_relation/sql_builder/select_builder_spec.rb
@@ -1,4 +1,4 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
+require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
describe SelectBuilder do
describe '#to_s' do
@@ -50,6 +50,22 @@ describe SelectBuilder do
WHERE 1 = `b`.`c`
""")
end
+
+ it 'accepts arbitrary strings' do
+ SelectBuilder.new do
+ select do
+ all
+ end
+ from :users
+ where do
+ value "'a' = 'a'"
+ end
+ end.to_s.should be_like("""
+ SELECT *
+ FROM `users`
+ WHERE 'a' = 'a'
+ """)
+ end
end
describe 'with inner join' do
@@ -68,7 +84,26 @@ describe SelectBuilder do
end
end.to_s.should be_like("""
SELECT *
- FROM `users` INNER JOIN `friendships` ON `users`.`id` = `friendships`.`user_id`
+ FROM `users`
+ INNER JOIN `friendships`
+ ON `users`.`id` = `friendships`.`user_id`
+ """)
+ end
+
+ it 'accepts arbitrary on strings' do
+ SelectBuilder.new do
+ select do
+ all
+ end
+ from :users do
+ inner_join :friendships do
+ value "arbitrary"
+ end
+ end
+ end.to_s.should be_like("""
+ SELECT *
+ FROM `users`
+ INNER JOIN `friendships` ON arbitrary
""")
end
end
diff --git a/spec/debug.log b/spec/debug.log
deleted file mode 100644
index d38ed11d82..0000000000
--- a/spec/debug.log
+++ /dev/null
@@ -1 +0,0 @@
-# Logfile created on Tue Jan 01 17:49:28 -0800 2008 by logger.rb/1.5.2.9
diff --git a/spec/extensions/range_spec.rb b/spec/extensions/range_spec.rb
deleted file mode 100644
index 26ca8978ca..0000000000
--- a/spec/extensions/range_spec.rb
+++ /dev/null
@@ -1 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
diff --git a/spec/integration/debug.log b/spec/integration/debug.log
deleted file mode 100644
index e69de29bb2..0000000000
--- a/spec/integration/debug.log
+++ /dev/null
diff --git a/spec/spec_helpers/be_like.rb b/spec/matchers/be_like.rb
index cea3f3027b..cea3f3027b 100644
--- a/spec/spec_helpers/be_like.rb
+++ b/spec/matchers/be_like.rb
diff --git a/spec/relations/relation_spec.rb b/spec/relations/relation_spec.rb
deleted file mode 100644
index d029827f21..0000000000
--- a/spec/relations/relation_spec.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', 'spec_helper')
-
-describe Relation do
- before do
- @relation1 = TableRelation.new(:foo)
- @relation2 = TableRelation.new(:bar)
- @attribute1 = Attribute.new(@relation1, :id)
- @attribute2 = Attribute.new(@relation1, :name)
- end
-
- describe 'joins' do
- describe '<=>' do
- it "manufactures an inner join operation between those two relations" do
- (@relation1 <=> @relation2).should == InnerJoinOperation.new(@relation1, @relation2)
- end
- end
-
- describe '<<' do
- it "manufactures a left outer join operation between those two relations" do
- (@relation1 << @relation2).should == LeftOuterJoinOperation.new(@relation1, @relation2)
- end
- end
- end
-
- describe '[]' do
- it "manufactures an attribute when given a symbol" do
- @relation1[:id].should be_eql(Attribute.new(@relation1, :id))
- end
-
- it "manufactures a range relation when given a range" do
- @relation1[1..2].should == RangeRelation.new(@relation1, 1..2)
- end
- end
-
- describe '#include?' do
- it "manufactures an inclusion predicate" do
- @relation1.include?(@attribute1).should == RelationInclusionPredicate.new(@attribute1, @relation1)
- end
- end
-
- describe '#project' do
- it "collapses identical projections" do
- pending
- end
-
- it "manufactures a projection relation" do
- @relation1.project(@attribute1, @attribute2).should == ProjectionRelation.new(@relation1, @attribute1, @attribute2)
- end
- end
-
- describe '#rename' do
- it "manufactures a rename relation" do
- @relation1.rename(@attribute1, :foo).should == RenameRelation.new(@relation1, @attribute1 => :foo)
- end
- end
-
- describe '#select' do
- before do
- @predicate = EqualityPredicate.new(@attribute1, @attribute2)
- end
-
- it "manufactures a selection relation" do
- @relation1.select(@attribute1, @attribute2).should == SelectionRelation.new(@relation1, @attribute1, @attribute2)
- end
- end
-
- describe 'order' do
- it "manufactures an order relation" do
- @relation1.order(@attribute1, @attribute2).should == OrderRelation.new(@relation1, @attribute1, @attribute2)
- end
- end
-end \ No newline at end of file
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 8d90e0dd51..8f5d76370c 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,8 +1,9 @@
require 'rubygems'
require 'spec'
-require 'rr'
-require File.join(File.dirname(__FILE__), '..', 'lib', 'sql_algebra')
-require File.join(File.dirname(__FILE__), 'spec_helpers', 'be_like')
+dir = File.dirname(__FILE__)
+$LOAD_PATH.unshift "#{dir}/../lib"
+Dir["#{dir}/matchers/*"].each { |m| require "#{dir}/matchers/#{File.basename(m)}" }
+require 'active_relation'
ActiveRecord::Base.configurations = {
'sql_algebra_test' => {