aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb')
-rw-r--r--activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb58
1 files changed, 58 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb
new file mode 100644
index 0000000000..e794f05340
--- /dev/null
+++ b/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb
@@ -0,0 +1,58 @@
+module ActiveRecord
+ module Associations
+ class Preloader
+ class HasAndBelongsToMany < CollectionAssociation #:nodoc:
+ attr_reader :join_table
+
+ def initialize(klass, records, reflection, preload_options)
+ super
+ @join_table = Arel::Table.new(options[:join_table]).alias('t0')
+ end
+
+ # Unlike the other associations, we want to get a raw array of rows so that we can
+ # access the aliased column on the join table
+ def records_for(ids)
+ scope = super
+ klass.connection.select_all(scope.arel.to_sql, 'SQL', scope.bind_values)
+ end
+
+ def owner_key_name
+ reflection.active_record_primary_key
+ end
+
+ def association_key_name
+ 'ar_association_key_name'
+ end
+
+ def association_key
+ join_table[reflection.foreign_key]
+ end
+
+ private
+
+ # Once we have used the join table column (in super), we manually instantiate the
+ # actual records
+ def associated_records_by_owner
+ super.each do |owner_key, rows|
+ rows.map! { |row| klass.instantiate(row) }
+ end
+ end
+
+ def build_scope
+ super.joins(join).select(join_select)
+ end
+
+ def join_select
+ association_key.as(Arel.sql(association_key_name))
+ end
+
+ def join
+ condition = table[reflection.association_primary_key].eq(
+ join_table[reflection.association_foreign_key])
+
+ table.create_join(join_table, table.create_on(condition))
+ end
+ end
+ end
+ end
+end