0
@@ -20,7 +20,13 @@ module ActiveRecord
0
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}'.")
0
+ class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError #:nodoc:
0
+ def initialize(owner_class_name, reflection, source_reflection)
0
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
0
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc:
0
def initialize(reflection)
0
through_reflection = reflection.through_reflection
0
@@ -529,6 +535,8 @@ module ActiveRecord
0
# * <tt>:source</tt>: Specifies the source association name used by <tt>has_many :through</tt> queries. Only use it if the name cannot be
0
# inferred from the association. <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either +:subscribers+ or
0
# +:subscriber+ on +Subscription+, unless a +:source+ is given.
0
+ # * <tt>:source_type</tt>: Specifies type of the source association used by <tt>has_many :through</tt> queries where the source association
0
+ # is a polymorphic belongs_to.
0
# * <tt>:uniq</tt> - if set to true, duplicates will be omitted from the collection. Useful in conjunction with :through.
0
@@ -1087,7 +1095,7 @@ module ActiveRecord
0
:class_name, :table_name, :foreign_key,
0
:exclusively_dependent, :dependent,
0
:select, :conditions, :include, :order, :group, :limit, :offset,
0
- :as, :through, :source,
0
+ :as, :through, :source,
:source_type,0
:finder_sql, :counter_sql,
0
:before_add, :after_add, :before_remove, :after_remove,
0
@@ -1491,57 +1499,65 @@ module ActiveRecord
0
when reflection.macro == :has_many && reflection.options[:through]
0
through_conditions = through_reflection.options[:conditions] ? "AND #{interpolate_sql(sanitize_sql(through_reflection.options[:conditions]))}" : ''
0
+ jt_foreign_key = jt_as_extra = jt_source_extra = jt_sti_extra = nil
0
+ first_key = second_key = as_extra = nil
0
if through_reflection.options[:as] # has_many :through against a polymorphic join
0
- polymorphic_foreign_key = through_reflection.options[:as].to_s + '_id'
0
- polymorphic_foreign_type = through_reflection.options[:as].to_s + '_type'
0
- " LEFT OUTER JOIN %s ON (%s.%s = %s.%s AND %s.%s = %s) " % [
0
- table_alias_for(through_reflection.klass.table_name, aliased_join_table_name),
0
- aliased_join_table_name, polymorphic_foreign_key,
0
- parent.aliased_table_name, parent.primary_key,
0
- aliased_join_table_name, polymorphic_foreign_type, klass.quote_value(parent.active_record.base_class.name)] +
0
- " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [table_name_and_alias,
0
- aliased_table_name, primary_key, aliased_join_table_name, options[:foreign_key] || reflection.klass.to_s.classify.foreign_key
0
+ jt_foreign_key = through_reflection.options[:as].to_s + '_id'
0
+ jt_as_extra = " AND %s.%s = %s" % [
0
+ aliased_join_table_name, reflection.active_record.connection.quote_column_name(through_reflection.options[:as].to_s + '_type'),
0
+ klass.quote_value(parent.active_record.base_class.name)
0
- if source_reflection.macro == :has_many && source_reflection.options[:as]
0
- " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [
0
- table_alias_for(through_reflection.klass.table_name, aliased_join_table_name), aliased_join_table_name,
0
- through_reflection.primary_key_name,
0
- parent.aliased_table_name, parent.primary_key] +
0
- " LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s " % [
0
- aliased_table_name, "#{source_reflection.options[:as]}_id",
0
- aliased_join_table_name, options[:foreign_key] || primary_key,
0
- aliased_table_name, "#{source_reflection.options[:as]}_type",
0
+ jt_foreign_key = through_reflection.primary_key_name
0
+ case source_reflection.macro
0
+ if source_reflection.options[:as]
0
+ first_key = "#{source_reflection.options[:as]}_id"
0
+ second_key = options[:foreign_key] || primary_key
0
+ as_extra = " AND %s.%s = %s" % [
0
+ aliased_table_name, reflection.active_record.connection.quote_column_name("#{source_reflection.options[:as]}_type"),
0
klass.quote_value(source_reflection.active_record.base_class.name)
0
- case source_reflection.macro
0
- first_key = primary_key
0
- second_key = source_reflection.options[:foreign_key] || klass.to_s.classify.foreign_key
0
- first_key = through_reflection.klass.base_class.to_s.classify.foreign_key
0
- second_key = options[:foreign_key] || primary_key
0
- extra = through_reflection.klass.descends_from_active_record? ? nil :
0
- aliased_join_table_name,
0
- reflection.active_record.connection.quote_column_name(through_reflection.active_record.inheritance_column),
0
- through_reflection.klass.quote_value(through_reflection.klass.name.demodulize)]
0
- " LEFT OUTER JOIN %s ON (%s.%s = %s.%s%s) " % [
0
- table_alias_for(through_reflection.klass.table_name, aliased_join_table_name),
0
- aliased_join_table_name, through_reflection.primary_key_name,
0
- parent.aliased_table_name, parent.primary_key, extra] +
0
- " LEFT OUTER JOIN %s ON (%s.%s = %s.%s) " % [
0
- aliased_table_name, first_key,
0
- aliased_join_table_name, second_key
0
+ first_key = through_reflection.klass.base_class.to_s.classify.foreign_key
0
+ second_key = options[:foreign_key] || primary_key
0
+ unless through_reflection.klass.descends_from_active_record?
0
+ jt_sti_extra = " AND %s.%s = %s" % [
0
+ aliased_join_table_name,
0
+ reflection.active_record.connection.quote_column_name(through_reflection.active_record.inheritance_column),
0
+ through_reflection.klass.quote_value(through_reflection.klass.name.demodulize)]
0
+ first_key = primary_key
0
+ if reflection.options[:source_type]
0
+ second_key = source_reflection.association_foreign_key
0
+ jt_source_extra = " AND %s.%s = %s" % [
0
+ aliased_join_table_name, reflection.active_record.connection.quote_column_name(reflection.source_reflection.options[:foreign_type]),
0
+ klass.quote_value(reflection.options[:source_type])
0
+ second_key = source_reflection.options[:foreign_key] || klass.to_s.classify.foreign_key
0
+ " LEFT OUTER JOIN %s ON (%s.%s = %s.%s%s%s%s) " % [
0
+ table_alias_for(through_reflection.klass.table_name, aliased_join_table_name),
0
+ parent.aliased_table_name, reflection.active_record.connection.quote_column_name(parent.primary_key),
0
+ aliased_join_table_name, reflection.active_record.connection.quote_column_name(jt_foreign_key),
0
+ jt_as_extra, jt_source_extra, jt_sti_extra
0
+ " LEFT OUTER JOIN %s ON (%s.%s = %s.%s%s) " % [
0
+ aliased_table_name, reflection.active_record.connection.quote_column_name(first_key),
0
+ aliased_join_table_name, reflection.active_record.connection.quote_column_name(second_key),
0
when reflection.macro == :has_many && reflection.options[:as]
0
" LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s" % [
0
@@ -1588,6 +1604,7 @@ module ActiveRecord
0
def pluralize(table_name)
0
ActiveRecord::Base.pluralize_table_names ? table_name.to_s.pluralize : table_name
Comments
No one has commented yet.