class ActiveRecord::Associations::HasManyThroughAssociation def construct_joins(custom_joins = nil) reflection = @reflection joins = [] while reflection.through_reflection joins << construct_one_join(reflection) reflection = reflection.through_reflection end "#{joins.join(' ')} #{custom_joins}" end def construct_one_join(reflection) polymorphic_join = nil if reflection.through_reflection.options[:as] || reflection.source_reflection.macro == :belongs_to reflection_primary_key = reflection.klass.primary_key source_primary_key = reflection.source_reflection.primary_key_name if reflection.options[:source_type] polymorphic_join = "AND %s.%s = %s" % [ reflection.through_reflection.table_name, "#{reflection.source_reflection.options[:foreign_type]}", @owner.class.quote_value(reflection.options[:source_type]) ] end else reflection_primary_key = reflection.source_reflection.primary_key_name source_primary_key = reflection.klass.primary_key if reflection.source_reflection.options[:as] polymorphic_join = "AND %s.%s = %s" % [ reflection.table_name, "#{reflection.source_reflection.options[:as]}_type", @owner.class.quote_value(reflection.through_reflection.klass.name) ] end end "INNER JOIN %s ON %s.%s = %s.%s %s #{reflection.options[:joins]}" % [ reflection.through_reflection.table_name, reflection.table_name, reflection_primary_key, reflection.through_reflection.table_name, source_primary_key, polymorphic_join ] end def last_through_reflection reflection = @reflection.through_reflection while reflection.through_reflection reflection = reflection.through_reflection end reflection end def construct_conditions table_name = last_through_reflection.table_name conditions = construct_quoted_owner_attributes(last_through_reflection).map do |attr, value| "#{table_name}.#{attr} = #{value}" end conditions << sql_conditions if sql_conditions "(" + conditions.join(') AND (') + ")" end def one_condition(reflection) [ (interpolate_sql(reflection.klass.send(:sanitize_sql, reflection.options[:conditions])) if reflection.options[:conditions]), ("#{reflection.table_name}.#{reflection.klass.inheritance_column} = #{reflection.klass.quote_value(reflection.klass.name.demodulize)}" unless reflection.klass.descends_from_active_record?) ] end def conditions conditions = [] reflection = @reflection while reflection conditions += one_condition(reflection) reflection = reflection.through_reflection end conditions.compact! @conditions ||= conditions.join(' AND ') unless conditions.empty? end alias_method :sql_conditions, :conditions end class ActiveRecord::Associations::AssociationCollection def new(options = {}) record = proxy_reflection.klass.new(options) set_belongs_to_association_for(record) record end end