aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb
diff options
context:
space:
mode:
authorGonçalo Silva <goncalossilva@gmail.com>2011-03-24 17:21:17 +0000
committerGonçalo Silva <goncalossilva@gmail.com>2011-03-24 17:21:17 +0000
commit9887f238871bb2dd73de6ce8855615bcc5d8d079 (patch)
tree74fa9ff9524a51701cfa23f708b3f777c65b7fe5 /activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb
parentaff821508a16245ebc03510ba29c70379718dfb7 (diff)
parent5214e73850916de3c9127d35a4ecee0424d364a3 (diff)
downloadrails-9887f238871bb2dd73de6ce8855615bcc5d8d079.tar.gz
rails-9887f238871bb2dd73de6ce8855615bcc5d8d079.tar.bz2
rails-9887f238871bb2dd73de6ce8855615bcc5d8d079.zip
Merge branch 'master' of https://github.com/rails/rails
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.rb60
1 files changed, 60 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..24be279449
--- /dev/null
+++ b/activerecord/lib/active_record/associations/preloader/has_and_belongs_to_many.rb
@@ -0,0 +1,60 @@
+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, ensuring that we don't create more than one instances of the same
+ # record
+ def associated_records_by_owner
+ records = {}
+ super.each do |owner_key, rows|
+ rows.map! { |row| records[row[klass.primary_key]] ||= 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