aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kallen <nkallen@nick-kallens-computer-2.local>2008-02-24 22:19:32 -0800
committerNick Kallen <nkallen@nick-kallens-computer-2.local>2008-02-24 22:19:32 -0800
commit92db013ba3ee4d0a9d92281e614d05f064c22e15 (patch)
tree23585e771ee1a2b1682f66a67d6b6891fab49f24
parentecd072d21951573f59e9515b868224d3732dbdfa (diff)
downloadrails-92db013ba3ee4d0a9d92281e614d05f064c22e15.tar.gz
rails-92db013ba3ee4d0a9d92281e614d05f064c22e15.tar.bz2
rails-92db013ba3ee4d0a9d92281e614d05f064c22e15.zip
quoting issues
-rw-r--r--lib/active_relation/extensions.rb1
-rw-r--r--lib/active_relation/extensions/base.rb48
-rw-r--r--lib/active_relation/extensions/object.rb6
-rw-r--r--lib/active_relation/predicates.rb5
-rw-r--r--lib/active_relation/primitives/attribute.rb18
-rw-r--r--lib/active_relation/primitives/expression.rb2
-rw-r--r--lib/active_relation/relations/compound.rb2
-rw-r--r--lib/active_relation/relations/join.rb2
-rw-r--r--lib/active_relation/relations/relation.rb4
-rw-r--r--lib/active_relation/relations/table.rb17
-rw-r--r--lib/active_relation/sql.rb23
-rw-r--r--spec/active_relation/integration/scratch_spec.rb252
-rw-r--r--spec/active_relation/unit/predicates/binary_spec.rb3
-rw-r--r--spec/active_relation/unit/predicates/equality_spec.rb8
-rw-r--r--spec/active_relation/unit/primitives/attribute_spec.rb41
-rw-r--r--spec/active_relation/unit/primitives/expression_spec.rb2
-rw-r--r--spec/active_relation/unit/relations/table_spec.rb8
17 files changed, 93 insertions, 349 deletions
diff --git a/lib/active_relation/extensions.rb b/lib/active_relation/extensions.rb
index 3751088483..8a024947ed 100644
--- a/lib/active_relation/extensions.rb
+++ b/lib/active_relation/extensions.rb
@@ -1,4 +1,3 @@
require 'active_relation/extensions/object'
require 'active_relation/extensions/array'
-require 'active_relation/extensions/base'
require 'active_relation/extensions/hash'
diff --git a/lib/active_relation/extensions/base.rb b/lib/active_relation/extensions/base.rb
deleted file mode 100644
index c1b823f9a7..0000000000
--- a/lib/active_relation/extensions/base.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-class ActiveRecord::Base
- class << self
- def cache
- @identity_map ||= IdentityMap.new
- end
-
- def relation
- @relation ||= ActiveRelation::Table.new(table_name)
- end
- end
-
- class IdentityMap
- def initialize
- @map = {}
- end
-
- def get(record, &block)
- @map[record] ||= yield
- end
- end
-end
-
-# all of the below disables normal AR behavior. It's rather destructive and purely for demonstration purposes (see scratch_spec).
-class ActiveRecord::Associations::BelongsToAssociation
- def instantiate(record, joins = [])
- @target = proxy_reflection.klass.instantiate(record, joins)
- loaded
- end
-
- # this basically disables belongs_to from loading themselves
- def reload
- @target = 'hack'
- end
-end
-
-class ActiveRecord::Associations::AssociationCollection
- def instantiate(record, joins = [])
- @target << proxy_reflection.klass.instantiate(record, joins)
- loaded # technically, this isn't true. doesn't matter though
- end
-end
-
-class ActiveRecord::Associations::HasManyThroughAssociation
- def instantiate(record, joins = [])
- @target << proxy_reflection.klass.instantiate(record, joins)
- loaded # again, not really true.
- end
-end \ No newline at end of file
diff --git a/lib/active_relation/extensions/object.rb b/lib/active_relation/extensions/object.rb
index 35ffa9c661..0cc87bf262 100644
--- a/lib/active_relation/extensions/object.rb
+++ b/lib/active_relation/extensions/object.rb
@@ -7,7 +7,11 @@ class Object
self
end
- def to_sql(strategy = ActiveRelation::Sql::Scalar.new)
+ def to_sql(strategy = self.strategy)
strategy.scalar self
end
+
+ def strategy
+ ActiveRelation::Sql::Scalar.new
+ end
end \ No newline at end of file
diff --git a/lib/active_relation/predicates.rb b/lib/active_relation/predicates.rb
index 7d0618f42e..2a36e65042 100644
--- a/lib/active_relation/predicates.rb
+++ b/lib/active_relation/predicates.rb
@@ -6,7 +6,6 @@ module ActiveRelation
end
class Binary < Predicate
- # rename "operand21", "operand22"
attr_reader :operand1, :operand2
def initialize(operand1, operand2)
@@ -25,8 +24,8 @@ module ActiveRelation
descend(&:qualify)
end
- def to_sql(strategy = Sql::Predicate.new)
- "#{operand1.to_sql(strategy)} #{predicate_sql} #{operand2.to_sql(strategy)}"
+ def to_sql(strategy = nil)
+ "#{operand1.to_sql(operand2.strategy)} #{predicate_sql} #{operand2.to_sql(operand1.strategy)}"
end
def descend
diff --git a/lib/active_relation/primitives/attribute.rb b/lib/active_relation/primitives/attribute.rb
index e55dd0bdc4..75f19605c7 100644
--- a/lib/active_relation/primitives/attribute.rb
+++ b/lib/active_relation/primitives/attribute.rb
@@ -2,8 +2,8 @@ module ActiveRelation
class Attribute
attr_reader :relation, :name, :alias, :ancestor
- def initialize(relation, name, aliaz = nil, ancestor = nil)
- @relation, @name, @alias, @ancestor = relation, name, aliaz, ancestor
+ def initialize(relation, name, options = {})
+ @relation, @name, @alias, @ancestor, @column = relation, name, options[:alias], options[:ancestor]
end
def alias_or_name
@@ -12,11 +12,11 @@ module ActiveRelation
module Transformations
def as(aliaz = nil)
- Attribute.new(relation, name, aliaz, self)
+ Attribute.new(relation, name, :alias => aliaz, :ancestor => self)
end
def bind(new_relation)
- relation == new_relation ? self : Attribute.new(new_relation, name, @alias, self)
+ relation == new_relation ? self : Attribute.new(new_relation, name, :alias => @alias, :ancestor => self)
end
def qualify
@@ -32,6 +32,10 @@ module ActiveRelation
def qualified_name
"#{prefix}.#{name}"
end
+
+ def column
+ relation.column_for(self)
+ end
def ==(other)
self.class == other.class and
@@ -112,10 +116,14 @@ module ActiveRelation
end
include Expressions
- def to_sql(strategy = Sql::Predicate.new)
+ def to_sql(strategy = self.strategy)
strategy.attribute prefix, name, self.alias
end
+ def strategy
+ Sql::Attribute.new(self)
+ end
+
private
def prefix
relation.prefix_for(self)
diff --git a/lib/active_relation/primitives/expression.rb b/lib/active_relation/primitives/expression.rb
index 35c1b5ff65..11aa558977 100644
--- a/lib/active_relation/primitives/expression.rb
+++ b/lib/active_relation/primitives/expression.rb
@@ -20,7 +20,7 @@ module ActiveRelation
end
def to_attribute
- Attribute.new(relation, @alias, nil, self)
+ Attribute.new(relation, @alias, :ancestor => self)
end
end
include Transformations
diff --git a/lib/active_relation/relations/compound.rb b/lib/active_relation/relations/compound.rb
index 094c6e29dd..115315a76a 100644
--- a/lib/active_relation/relations/compound.rb
+++ b/lib/active_relation/relations/compound.rb
@@ -2,7 +2,7 @@ module ActiveRelation
class Compound < Relation
attr_reader :relation
delegate :joins, :selects, :orders, :groupings, :table_sql, :inserts, :limit,
- :offset, :name, :alias, :aggregation?, :alias?, :prefix_for,
+ :offset, :name, :alias, :aggregation?, :alias?, :prefix_for, :column_for,
:to => :relation
def attributes
diff --git a/lib/active_relation/relations/join.rb b/lib/active_relation/relations/join.rb
index 70c85bb1e0..8e0dcb2a4b 100644
--- a/lib/active_relation/relations/join.rb
+++ b/lib/active_relation/relations/join.rb
@@ -38,7 +38,7 @@ module ActiveRelation
join_sql,
externalize(relation2).table_sql,
"ON",
- predicates.collect { |p| p.bind(self).to_sql(Sql::Predicate.new) }.join(' AND ')
+ predicates.collect { |p| p.bind(self).to_sql }.join(' AND ')
].join(" ")
[relation1.joins, relation2.joins, this_join].compact.join(" ")
end
diff --git a/lib/active_relation/relations/relation.rb b/lib/active_relation/relations/relation.rb
index 1d5e194923..7536390aca 100644
--- a/lib/active_relation/relations/relation.rb
+++ b/lib/active_relation/relations/relation.rb
@@ -104,12 +104,12 @@ module ActiveRelation
false
end
- def to_sql(strategy = Sql::Select.new)
+ def to_sql(strategy = Sql::Relation.new)
strategy.select [
"SELECT #{attributes.collect{ |a| a.to_sql(Sql::Projection.new) }.join(', ')}",
"FROM #{table_sql}",
(joins unless joins.blank?),
- ("WHERE #{selects.collect{|s| s.to_sql(Sql::Predicate.new)}.join("\n\tAND ")}" unless selects.blank?),
+ ("WHERE #{selects.collect{|s| s.to_sql(Sql::Selection.new)}.join("\n\tAND ")}" unless selects.blank?),
("ORDER BY #{orders.collect(&:to_sql)}" unless orders.blank?),
("GROUP BY #{groupings.collect(&:to_sql)}" unless groupings.blank?),
("LIMIT #{limit.to_sql}" unless limit.blank?),
diff --git a/lib/active_relation/relations/table.rb b/lib/active_relation/relations/table.rb
index d0fc2b2475..5720be30e3 100644
--- a/lib/active_relation/relations/table.rb
+++ b/lib/active_relation/relations/table.rb
@@ -3,11 +3,11 @@ module ActiveRelation
attr_reader :name
def initialize(name)
- @name = name
+ @name = name.to_s
end
def attributes
- @attributes ||= connection.columns(name, "#{name} Columns").collect do |column|
+ @attributes ||= columns.collect do |column|
Attribute.new(self, column.name.to_sym)
end
end
@@ -19,7 +19,20 @@ module ActiveRelation
def prefix_for(attribute)
self[attribute] and name
end
+
+ def column_for(attribute)
+ self[attribute] and columns.detect { |c| c.name == attribute.name }
+ end
+
+ def ==(other)
+ self.class == other.class and
+ name == other.name
+ end
+ def columns
+ @columns ||= connection.columns(name, "#{name} Columns")
+ end
+
protected
def table_sql
"#{quote_table_name(name)}"
diff --git a/lib/active_relation/sql.rb b/lib/active_relation/sql.rb
index 85bcb4107b..49ced3cbaa 100644
--- a/lib/active_relation/sql.rb
+++ b/lib/active_relation/sql.rb
@@ -27,8 +27,8 @@ module ActiveRelation
"#{quote_table_name(relation_name)}.#{quote_column_name(attribute_name)}"
end
- def scalar(scalar)
- scalar
+ def scalar(scalar, column = nil)
+ quote(scalar, column)
end
def select(select_sql, aliaz)
@@ -36,7 +36,13 @@ module ActiveRelation
end
end
- class Select < Strategy
+ class Selection < Strategy
+ def scalar(scalar)
+ scalar
+ end
+ end
+
+ class Relation < Strategy
def select(select_sql, aliaz)
select_sql
end
@@ -48,10 +54,17 @@ module ActiveRelation
end
end
- class Scalar < Strategy
+ class Attribute < Predicate
+ def initialize(attribute)
+ @attribute = attribute
+ end
+
def scalar(scalar)
- quote(scalar)
+ quote(scalar, @attribute.column)
end
end
+
+ class Scalar < Predicate
+ end
end
end \ No newline at end of file
diff --git a/spec/active_relation/integration/scratch_spec.rb b/spec/active_relation/integration/scratch_spec.rb
deleted file mode 100644
index d6ec030518..0000000000
--- a/spec/active_relation/integration/scratch_spec.rb
+++ /dev/null
@@ -1,252 +0,0 @@
-require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
-
-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
- advantages over flexible SQL builders like Sequel and and
- SqlAlchemy (a beautiful Python library). Principally, a
- relation is writable as well as readable. This obviates the
- :create with_scope, and perhaps also
- #set_belongs_to_association_for.
- With so much complexity removed from ActiveRecord, I
- propose a mild reconsideration of the architecture of Base,
- AssocationProxy, AssociationCollection, and so forth. These
- 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 smaller and
- more consistent.' do
- before do
- class User < ActiveRecord::Base; has_many :photos end
- class Photo < ActiveRecord::Base; belongs_to :camera end
- class Camera < ActiveRecord::Base; end
- end
-
- before do
- # Rather than being associated with a table, an ActiveRecord is now associated with
- # a relation.
- @users = User.relation
- @photos = Photo.relation
- @cameras = Camera.relation
- # A first taste of a Relational Algebra: User.find(1)
- @user = @users.select(@users[:id].equals(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
- # mapping from one relation to another. The Reflection object parameterizes the
- # mapping.
- def user_has_many_photos(user_relation)
- primary_key = User.reflections[:photos].klass.primary_key.to_sym
- foreign_key = User.reflections[:photos].primary_key_name.to_sym
-
- user_relation.outer_join(@photos).on(user_relation[primary_key].equals(@photos[foreign_key]))
- end
-
- def photo_belongs_to_camera(photo_relation)
- primary_key = Photo.reflections[:camera].klass.primary_key.to_sym
- foreign_key = Photo.reflections[:camera].primary_key_name.to_sym
-
- photo_relation.outer_join(@cameras).on(photo_relation[foreign_key].equals(@cameras[primary_key]))
- end
-
- describe 'Relational Algebra', 'a relational algebra allows the implementation of
- associations like has_many to be specified once,
- regardless of eager-joins, has_many :through, and so
- forth' do
- it 'generates the query for User.has_many :photos' do
- user_photos = user_has_many_photos(@user)
- # the 'project' operator limits the columns that come back from the query.
- # Note how all the operators are compositional: 'project' is applied to a query
- # that previously had been joined and selected.
- user_photos.project(*@photos.attributes).to_sql.should be_like("""
- SELECT `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
- FROM `users`
- LEFT OUTER JOIN `photos`
- ON `users`.`id` = `photos`.`user_id`
- WHERE
- `users`.`id` = 1
- """)
- # Also note the correctly quoted columns and tables. In this instance the
- # MysqlAdapter from ActiveRecord is used to do the escaping.
- end
-
- it 'generates the query for User.has_many :cameras, :through => :photos' do
- # note, again, the compositionality of the operators:
- user_cameras = photo_belongs_to_camera(user_has_many_photos(@user))
- user_cameras.project(*@cameras.attributes).to_sql.should be_like("""
- SELECT `cameras`.`id`
- FROM `users`
- LEFT OUTER JOIN `photos`
- ON `users`.`id` = `photos`.`user_id`
- LEFT OUTER JOIN `cameras`
- ON `photos`.`camera_id` = `cameras`.`id`
- WHERE
- `users`.`id` = 1
- """)
- end
-
- it 'generates the query for an eager join for a collection using the same logic as
- for an association on an individual row' do
- users_cameras = photo_belongs_to_camera(user_has_many_photos(@users))
- users_cameras.to_sql.should be_like("""
- SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`, `cameras`.`id`
- FROM `users`
- LEFT OUTER JOIN `photos`
- ON `users`.`id` = `photos`.`user_id`
- LEFT OUTER JOIN `cameras`
- ON `photos`.`camera_id` = `cameras`.`id`
- """)
- end
-
- it 'is trivial to disambiguate columns' do
- users_cameras = photo_belongs_to_camera(user_has_many_photos(@users)).qualify
- users_cameras.to_sql.should be_like("""
- SELECT `users`.`id` AS 'users.id', `users`.`name` AS 'users.name', `photos`.`id` AS 'photos.id', `photos`.`user_id` AS 'photos.user_id', `photos`.`camera_id` AS 'photos.camera_id', `cameras`.`id` AS 'cameras.id'
- FROM `users`
- LEFT OUTER JOIN `photos`
- ON `users`.`id` = `photos`.`user_id`
- LEFT OUTER JOIN `cameras`
- ON `photos`.`camera_id` = `cameras`.`id`
- """)
- end
-
- it 'allows arbitrary sql to be passed through' do
- @users.outer_join(@photos).on("asdf").to_sql.should be_like("""
- SELECT `users`.`id`, `users`.`name`, `photos`.`id`, `photos`.`user_id`, `photos`.`camera_id`
- FROM `users`
- LEFT OUTER JOIN `photos`
- ON asdf
- """)
- @users.select("asdf").to_sql.should be_like("""
- SELECT `users`.`id`, `users`.`name`
- FROM `users`
- WHERE asdf
- """)
- 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
- end
- end
- end
-
- describe 'Repository', 'ActiveRecord::Base, HasManyAssociation, and so forth are
- all repositories: given a relation, they manufacture objects' do
- before do
- class << ActiveRecord::Base; public :instantiate end
- end
-
- it 'manufactures objects' do
- User.instantiate(@users.first).attributes.should == {"name" => "hai", "id" => 1}
- end
-
- it 'frees ActiveRecords from being tied to tables' do
- pending # pending, but trivial to implement:
-
- class User < ActiveRecord::Base
- # acts_as_paranoid without alias_method_chain:
- set_relation @users.select(@users[:deleted_at] != nil)
- end
-
- class Person < ActiveRecord::Base
- set_relation @accounts.join(@profiles).on(@accounts[:id].equals(@profiles[:account_id]))
- end
- # I know this sounds crazy, but even writes are possible in the last example.
- # calling #save on a person can write to two tables!
- end
-
- describe 'the n+1 problem' do
- describe 'the eager join algorithm is vastly simpler' 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}
- end
-
- before do
- class << ActiveRecord::Base
- # An identity map makes this algorithm efficient.
- def instantiate_with_cache(record)
- cache.get(record) { instantiate_without_cache(record) }
- end
- alias_method_chain :instantiate, :cache
-
- # for each row in the result set, which may contain data from n tables,
- # - instantiate that slice of the data corresponding to the current class
- # - recusively walk the dependency chain and repeat.
- def instantiate_with_joins(data, joins = [])
- record = unqualify(data)
- returning instantiate_without_joins(record) do |object|
- joins.each do |join|
- case join
- when Symbol
- object.send(association = join).instantiate(data)
- when Hash
- join.each do |association, nested_associations|
- object.send(association).instantiate(data, nested_associations)
- end
- end
- end
- end
- end
- alias_method_chain :instantiate, :joins
-
- private
- # Sometimes, attributes are qualified to remove ambiguity. Here, bring back
- # ambiguity by translating 'users.id' to 'id' so we can call #attributes=.
- # This code should work correctly if the attributes are qualified or not.
- def unqualify(qualified_attributes)
- qualified_attributes_for_this_class = qualified_attributes. \
- slice(*relation.attributes.collect(&:qualified_name))
- qualified_attributes_for_this_class.alias do |qualified_name|
- qualified_name.split('.')[1] || qualified_name # the latter means it must not really be qualified
- end
- end
- end
- end
-
- it "is possible to be smarter about eager loading. DataMapper is smart enough
- to notice when you do users.each { |u| u.photos } and make this two queries
- rather than n+1: the first invocation of #photos is lazy but it preloads
- 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." 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/active_relation/unit/predicates/binary_spec.rb b/spec/active_relation/unit/predicates/binary_spec.rb
index 44c1a1a7a0..1f6656b9d1 100644
--- a/spec/active_relation/unit/predicates/binary_spec.rb
+++ b/spec/active_relation/unit/predicates/binary_spec.rb
@@ -53,6 +53,9 @@ module ActiveRelation
`users`.`id` <=> `photos`.`id`
""")
end
+
+ it 'appropriately cooerces scalars' do
+ end
end
end
end \ No newline at end of file
diff --git a/spec/active_relation/unit/predicates/equality_spec.rb b/spec/active_relation/unit/predicates/equality_spec.rb
index fd30846c70..499b13383d 100644
--- a/spec/active_relation/unit/predicates/equality_spec.rb
+++ b/spec/active_relation/unit/predicates/equality_spec.rb
@@ -3,10 +3,10 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper')
module ActiveRelation
describe Equality do
before do
- @relation1 = Table.new(:foo)
- @relation2 = Table.new(:bar)
- @attribute1 = Attribute.new(@relation1, :name)
- @attribute2 = Attribute.new(@relation2, :name)
+ @relation1 = Table.new(:users)
+ @relation2 = Table.new(:photos)
+ @attribute1 = @relation1[:name]
+ @attribute2 = @relation2[:name]
end
describe '==' do
diff --git a/spec/active_relation/unit/primitives/attribute_spec.rb b/spec/active_relation/unit/primitives/attribute_spec.rb
index e5a3792d85..8b4f52c432 100644
--- a/spec/active_relation/unit/primitives/attribute_spec.rb
+++ b/spec/active_relation/unit/primitives/attribute_spec.rb
@@ -4,23 +4,20 @@ module ActiveRelation
describe Attribute do
before do
@relation = Table.new(:users)
+ @attribute = Attribute.new(@relation, :id)
end
describe Attribute::Transformations do
- before do
- @attribute = Attribute.new(@relation, :id)
- end
-
describe '#as' do
it "manufactures an aliased attributed" do
- @attribute.as(:alias).should == Attribute.new(@relation, @attribute.name, :alias, @attribute)
+ @attribute.as(:alias).should == Attribute.new(@relation, @attribute.name, :alias => :alias, :ancestor => @attribute)
end
end
describe '#bind' do
it "manufactures an attribute with the relation bound and self as an ancestor" do
derived_relation = @relation.select(@relation[:id].equals(1))
- @attribute.bind(derived_relation).should == Attribute.new(derived_relation, @attribute.name, nil, @attribute)
+ @attribute.bind(derived_relation).should == Attribute.new(derived_relation, @attribute.name, :ancestor => @attribute)
end
it "returns self if the substituting to the same relation" do
@@ -30,7 +27,7 @@ module ActiveRelation
describe '#qualify' do
it "manufactures an attribute aliased with that attribute's qualified name" do
- @attribute.qualify.should == Attribute.new(@attribute.relation, @attribute.name, @attribute.qualified_name, @attribute)
+ @attribute.qualify.should == Attribute.new(@attribute.relation, @attribute.name, :alias => @attribute.qualified_name, :ancestor => @attribute)
end
end
@@ -41,9 +38,16 @@ module ActiveRelation
end
end
+ describe '#column' do
+ it "" do
+ pending
+ end
+ end
+
describe '#qualified_name' do
it "manufactures an attribute name prefixed with the relation's name" do
- Attribute.new(@relation, :id).qualified_name.should == 'users.id'
+ stub(@relation).prefix_for(anything) { 'bruisers' }
+ Attribute.new(@relation, :id).qualified_name.should == 'bruisers.id'
end
end
@@ -54,25 +58,20 @@ module ActiveRelation
end
it "obtains if the attributes have an overlapping history" do
- Attribute.new(@relation, :name, nil, Attribute.new(@relation, :name)).should =~ Attribute.new(@relation, :name)
- Attribute.new(@relation, :name).should =~ Attribute.new(@relation, :name, nil, Attribute.new(@relation, :name))
+ Attribute.new(@relation, :name, :ancestor => Attribute.new(@relation, :name)).should =~ Attribute.new(@relation, :name)
+ Attribute.new(@relation, :name).should =~ Attribute.new(@relation, :name, :ancestor => Attribute.new(@relation, :name))
end
end
end
describe '#to_sql' do
- describe Sql::Strategy do
- before do
- stub(@relation).prefix_for(anything) { 'bruisers' }
- end
-
- it "manufactures sql without an alias if the strategy is Predicate" do
- Attribute.new(@relation, :name, :alias).to_sql(Sql::Predicate.new).should be_like("`bruisers`.`name`")
- end
+ it "" do
+ pending "this test is not sufficiently resilient"
+ end
- it "manufactures sql with an alias if the strategy is Projection" do
- Attribute.new(@relation, :name, :alias).to_sql(Sql::Projection.new).should be_like("`bruisers`.`name` AS 'alias'")
- end
+ it "manufactures sql with an alias" do
+ stub(@relation).prefix_for(anything) { 'bruisers' }
+ Attribute.new(@relation, :name, :alias => :alias).to_sql.should be_like("`bruisers`.`name`")
end
end
diff --git a/spec/active_relation/unit/primitives/expression_spec.rb b/spec/active_relation/unit/primitives/expression_spec.rb
index 5506f52b86..dda35157b0 100644
--- a/spec/active_relation/unit/primitives/expression_spec.rb
+++ b/spec/active_relation/unit/primitives/expression_spec.rb
@@ -31,7 +31,7 @@ module ActiveRelation
describe '#to_attribute' do
it "manufactures an attribute with the expression as an ancestor" do
- @expression.to_attribute.should == Attribute.new(@expression.relation, @expression.alias, nil, @expression)
+ @expression.to_attribute.should == Attribute.new(@expression.relation, @expression.alias, :ancestor => @expression)
end
end
end
diff --git a/spec/active_relation/unit/relations/table_spec.rb b/spec/active_relation/unit/relations/table_spec.rb
index 3b02f80701..f8d4431aa7 100644
--- a/spec/active_relation/unit/relations/table_spec.rb
+++ b/spec/active_relation/unit/relations/table_spec.rb
@@ -45,9 +45,15 @@ module ActiveRelation
end
end
+ describe '#column_for' do
+ it "" do
+ pending
+ end
+ end
+
describe '#prefix_for' do
it "returns the table name if the relation contains the attribute" do
- @relation.prefix_for(@relation[:id]).should == :users
+ @relation.prefix_for(@relation[:id]).should == 'users'
@relation.prefix_for(:does_not_exist).should be_nil
end
end