Remove various comments and code which were just being used during the development of nested through association support (OMFGZ, I might just have nearly finished this\!

This commit is contained in:
Jon Leighton
2010-10-19 17:29:19 +01:00
parent 82b889f7d3
commit 7ee33b80a2
5 changed files with 0 additions and 199 deletions

View File

@@ -39,14 +39,6 @@ module ActiveRecord
end
end
class HasManyThroughSourceAssociationMacroError < ActiveRecordError #:nodoc:
def initialize(reflection)
through_reflection = reflection.through_reflection
source_reflection = reflection.source_reflection
super("Invalid source reflection macro :#{source_reflection.macro}#{" :through" if source_reflection.options[:through]} for has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}. Use :source to specify the source reflection.")
end
end
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError #:nodoc:
def initialize(owner, reflection)
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")

View File

@@ -1,158 +0,0 @@
# TODO: Remove in the end, when its functionality is fully integrated in ThroughAssociationScope.
module ActiveRecord
module Associations
module NestedHasManyThrough
def self.included(klass)
klass.alias_method_chain :construct_conditions, :nesting
klass.alias_method_chain :construct_joins, :nesting
end
def construct_joins_with_nesting(custom_joins = nil)
if nested?
@nested_join_attributes ||= construct_nested_join_attributes
"#{construct_nested_join_attributes[:joins]} #{@reflection.options[:joins]} #{custom_joins}"
else
construct_joins_without_nesting(custom_joins)
end
end
def construct_conditions_with_nesting
if nested?
@nested_join_attributes ||= construct_nested_join_attributes
if @reflection.through_reflection && @reflection.through_reflection.macro == :belongs_to
"#{@nested_join_attributes[:remote_key]} = #{belongs_to_quoted_key} #{@nested_join_attributes[:conditions]}"
else
"#{@nested_join_attributes[:remote_key]} = #{@owner.quoted_id} #{@nested_join_attributes[:conditions]}"
end
else
construct_conditions_without_nesting
end
end
protected
# Given any belongs_to or has_many (including has_many :through) association,
# return the essential components of a join corresponding to that association, namely:
#
# * <tt>:joins</tt>: any additional joins required to get from the association's table
# (reflection.table_name) to the table that's actually joining to the active record's table
# * <tt>:remote_key</tt>: the name of the key in the join table (qualified by table name) which will join
# to a field of the active record's table
# * <tt>:local_key</tt>: the name of the key in the local table (not qualified by table name) which will
# take part in the join
# * <tt>:conditions</tt>: any additional conditions (e.g. filtering by type for a polymorphic association,
# or a :conditions clause explicitly given in the association), including a leading AND
def construct_nested_join_attributes(reflection = @reflection, association_class = reflection.klass, table_ids = {association_class.table_name => 1})
if (reflection.macro == :has_many || reflection.macro == :has_one) && reflection.through_reflection
construct_has_many_through_attributes(reflection, table_ids)
else
construct_has_many_or_belongs_to_attributes(reflection, association_class, table_ids)
end
end
def construct_has_many_through_attributes(reflection, table_ids)
# Construct the join components of the source association, so that we have a path from
# the eventual target table of the association up to the table named in :through, and
# all tables involved are allocated table IDs.
source_attrs = construct_nested_join_attributes(reflection.source_reflection, reflection.klass, table_ids)
# Determine the alias of the :through table; this will be the last table assigned
# when constructing the source join components above.
through_table_alias = through_table_name = reflection.through_reflection.table_name
through_table_alias += "_#{table_ids[through_table_name]}" unless table_ids[through_table_name] == 1
# Construct the join components of the through association, so that we have a path to
# the active record's table.
through_attrs = construct_nested_join_attributes(reflection.through_reflection, reflection.through_reflection.klass, table_ids)
# Any subsequent joins / filters on owner attributes will act on the through association,
# so that's what we return for the conditions/keys of the overall association.
conditions = through_attrs[:conditions]
conditions += " AND #{interpolate_sql(reflection.klass.send(:sanitize_sql, reflection.options[:conditions]))}" if reflection.options[:conditions]
{
:joins => "%s INNER JOIN %s ON ( %s = %s.%s %s) %s %s" % [
source_attrs[:joins],
through_table_name == through_table_alias ? through_table_name : "#{through_table_name} #{through_table_alias}",
source_attrs[:remote_key],
through_table_alias, source_attrs[:local_key],
source_attrs[:conditions],
through_attrs[:joins],
reflection.options[:joins]
],
:remote_key => through_attrs[:remote_key],
:local_key => through_attrs[:local_key],
:conditions => conditions
}
end
# reflection is not has_many :through; it's a standard has_many / belongs_to instead
# TODO: see if we can defer to rails code here a bit more
def construct_has_many_or_belongs_to_attributes(reflection, association_class, table_ids)
# Determine the alias used for remote_table_name, if any. In all cases this will already
# have been assigned an ID in table_ids (either through being involved in a previous join,
# or - if it's the first table in the query - as the default value of table_ids)
remote_table_alias = remote_table_name = association_class.table_name
remote_table_alias += "_#{table_ids[remote_table_name]}" unless table_ids[remote_table_name] == 1
# Assign a new alias for the local table.
local_table_alias = local_table_name = reflection.active_record.table_name
if table_ids[local_table_name]
table_id = table_ids[local_table_name] += 1
local_table_alias += "_#{table_id}"
else
table_ids[local_table_name] = 1
end
conditions = ''
# Add type_condition, if applicable
conditions += " AND #{association_class.send(:type_condition).to_sql}" if association_class.finder_needs_type_condition?
# Add custom conditions
conditions += " AND (#{interpolate_sql(association_class.send(:sanitize_sql, reflection.options[:conditions]))})" if reflection.options[:conditions]
if reflection.macro == :belongs_to
if reflection.options[:polymorphic]
conditions += " AND #{local_table_alias}.#{reflection.options[:foreign_type]} = #{reflection.active_record.quote_value(association_class.base_class.name.to_s)}"
end
{
:joins => reflection.options[:joins],
:remote_key => "#{remote_table_alias}.#{association_class.primary_key}",
:local_key => reflection.primary_key_name,
:conditions => conditions
}
else
# Association is has_many (without :through)
if reflection.options[:as]
conditions += " AND #{remote_table_alias}.#{reflection.options[:as]}_type = #{reflection.active_record.quote_value(reflection.active_record.base_class.name.to_s)}"
end
{
:joins => "#{reflection.options[:joins]}",
:remote_key => "#{remote_table_alias}.#{reflection.primary_key_name}",
:local_key => reflection.klass.primary_key,
:conditions => conditions
}
end
end
def belongs_to_quoted_key
attribute = @reflection.through_reflection.primary_key_name
column = @owner.column_for_attribute attribute
@owner.send(:quote_value, @owner.send(attribute), column)
end
def nested?
through_source_reflection? || through_through_reflection?
end
def through_source_reflection?
@reflection.source_reflection && @reflection.source_reflection.options[:through]
end
def through_through_reflection?
@reflection.through_reflection && @reflection.through_reflection.options[:through]
end
end
end
end

View File

@@ -61,10 +61,6 @@ module ActiveRecord
end
def construct_joins(custom_joins = nil)
# TODO: Remove this at the end
#p @reflection.through_reflection_chain
#p @reflection.through_conditions
"#{construct_through_joins} #{@reflection.options[:joins]} #{custom_joins}"
end

View File

@@ -131,14 +131,6 @@ module ActiveRecord
@sanitized_conditions ||= klass.send(:sanitize_sql, options[:conditions]) if options[:conditions]
end
# TODO: Remove these in the final patch. I am just using them for debugging etc.
def inspect
"#<#{code_name}>"
end
def code_name
"#{active_record.name}.#{macro} :#{name}"
end
private
def derive_class_name
name.to_s.camelize
@@ -325,16 +317,6 @@ module ActiveRecord
def belongs_to?
macro == :belongs_to
end
# TODO: Remove for final patch. Just here for debugging.
def inspect
str = "#<#{code_name}, @source_reflection="
str << (source_reflection.respond_to?(:code_name) ? source_reflection.code_name : source_reflection.inspect)
str << ", @through_reflection="
str << (through_reflection.respond_to?(:code_name) ? through_reflection.code_name : through_reflection.inspect)
str << ">"
str
end
private
def derive_class_name
@@ -497,12 +479,6 @@ module ActiveRecord
raise HasManyThroughAssociationPolymorphicError.new(active_record.name, self, source_reflection)
end
# TODO: Presumably remove the HasManyThroughSourceAssociationMacroError class and delete these lines.
# Think about whether there are any cases which should still be disallowed.
# unless [:belongs_to, :has_many, :has_one].include?(source_reflection.macro) && source_reflection.options[:through].nil?
# raise HasManyThroughSourceAssociationMacroError.new(self)
# end
check_validity_of_inverse!
end

View File

@@ -23,11 +23,6 @@ require 'models/categorization'
require 'models/membership'
require 'models/essay'
# NOTE: Some of these tests might not really test "nested" HMT associations, as opposed to ones which
# are just one level deep. But it's all the same thing really, as the "nested" code is being
# written in a generic way which applies to "non-nested" HMT associations too. So let's just shove
# all useful tests in here for now and then work out where they ought to live properly later.
class NestedHasManyThroughAssociationsTest < ActiveRecord::TestCase
fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings,
:people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details,