Skip to content
This repository
Browse code

Fix preloading of has_one :through associations on belongs_to [#1507

…state:resolved]

Signed-off-by: Frederick Cheung <frederick.cheung@gmail.com>
  • Loading branch information...
commit a9422cc1db9501a80ecf2c25a5d3b0c4f4f32763 1 parent 8326b95
Matt Jones authored December 02, 2008 lifo committed December 18, 2008
15  activerecord/lib/active_record/association_preload.rb
@@ -204,9 +204,18 @@ def preload_has_one_association(records, reflection, preload_options={})
204 204
           unless through_records.empty?
205 205
             source = reflection.source_reflection.name
206 206
             through_records.first.class.preload_associations(through_records, source)
207  
-            through_records.each do |through_record|
208  
-              add_preloaded_record_to_collection(id_to_record_map[through_record[through_primary_key].to_s],
209  
-                                                 reflection.name, through_record.send(source))
  207
+            if through_reflection.macro == :belongs_to
  208
+              rev_id_to_record_map, rev_ids = construct_id_map(records, through_primary_key)
  209
+              rev_primary_key = through_reflection.klass.primary_key
  210
+              through_records.each do |through_record|
  211
+                add_preloaded_record_to_collection(rev_id_to_record_map[through_record[rev_primary_key].to_s],
  212
+                                                   reflection.name, through_record.send(source))
  213
+              end
  214
+            else
  215
+              through_records.each do |through_record|
  216
+                add_preloaded_record_to_collection(id_to_record_map[through_record[through_primary_key].to_s],
  217
+                                                   reflection.name, through_record.send(source))
  218
+              end
210 219
             end
211 220
           end
212 221
         else
6  activerecord/lib/active_record/associations/association_collection.rb
@@ -83,7 +83,11 @@ def last(*args)
83 83
 
84 84
       def to_ary
85 85
         load_target
86  
-        @target.to_ary
  86
+        if @target.is_a?(Array)
  87
+          @target.to_ary
  88
+        else
  89
+          Array(@target)
  90
+        end
87 91
       end
88 92
 
89 93
       def reset
17  activerecord/test/cases/associations/has_one_through_associations_test.rb
... ...
@@ -1,5 +1,6 @@
1 1
 require "cases/helper"
2 2
 require 'models/club'
  3
+require 'models/member_type'
3 4
 require 'models/member'
4 5
 require 'models/membership'
5 6
 require 'models/sponsor'
@@ -7,7 +8,7 @@
7 8
 require 'models/member_detail'
8 9
 
9 10
 class HasOneThroughAssociationsTest < ActiveRecord::TestCase
10  
-  fixtures :members, :clubs, :memberships, :sponsors, :organizations
  11
+  fixtures :member_types, :members, :clubs, :memberships, :sponsors, :organizations
11 12
   
12 13
   def setup
13 14
     @member = members(:groucho)
@@ -158,4 +159,18 @@ def test_reassigning_has_one_through
158 159
     assert @new_organization.members.include?(@member)
159 160
   end
160 161
 
  162
+  def test_preloading_has_one_through_on_belongs_to
  163
+    assert_not_nil @member.member_type
  164
+    @organization = organizations(:nsa)
  165
+    @member_detail = MemberDetail.new
  166
+    @member.member_detail = @member_detail
  167
+    @member.organization = @organization
  168
+    @member_details = assert_queries(3) do
  169
+      MemberDetail.find(:all, :include => :member_type)
  170
+    end
  171
+    @new_detail = @member_details[0]
  172
+    assert @new_detail.loaded_member_type?
  173
+    assert_not_nil assert_no_queries { @new_detail.member_type }
  174
+  end
  175
+
161 176
 end
6  activerecord/test/fixtures/member_types.yml
... ...
@@ -0,0 +1,6 @@
  1
+founding:
  2
+  id: 1
  3
+  name: Founding
  4
+provisional:
  5
+  id: 2
  6
+  name: Provisional
4  activerecord/test/fixtures/members.yml
... ...
@@ -1,4 +1,6 @@
1 1
 groucho:
2 2
   name: Groucho Marx
  3
+  member_type_id: 1
3 4
 some_other_guy:
4  
-  name: Englebert Humperdink
  5
+  name: Englebert Humperdink
  6
+  member_type_id: 2
1  activerecord/test/models/member.rb
@@ -8,4 +8,5 @@ class Member < ActiveRecord::Base
8 8
   has_one :sponsor_club, :through => :sponsor
9 9
   has_one :member_detail
10 10
   has_one :organization, :through => :member_detail
  11
+  belongs_to :member_type
11 12
 end
1  activerecord/test/models/member_detail.rb
... ...
@@ -1,4 +1,5 @@
1 1
 class MemberDetail < ActiveRecord::Base
2 2
   belongs_to :member
3 3
   belongs_to :organization
  4
+  has_one :member_type, :through => :member
4 5
 end
3  activerecord/test/models/member_type.rb
... ...
@@ -0,0 +1,3 @@
  1
+class MemberType < ActiveRecord::Base
  2
+  has_many :members
  3
+end
5  activerecord/test/schema/schema.rb
@@ -195,6 +195,7 @@ def create_table(*args, &block)
195 195
 
196 196
   create_table :members, :force => true do |t|
197 197
     t.string :name
  198
+    t.integer :member_type_id
198 199
   end
199 200
 
200 201
   create_table :member_details, :force => true do |t|
@@ -210,6 +211,10 @@ def create_table(*args, &block)
210 211
     t.string :type
211 212
   end
212 213
 
  214
+  create_table :member_types, :force => true do |t|
  215
+    t.string :name
  216
+  end
  217
+
213 218
   create_table :references, :force => true do |t|
214 219
     t.integer :person_id
215 220
     t.integer :job_id

0 notes on commit a9422cc

Please sign in to comment.
Something went wrong with that request. Please try again.