Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #9640: fix_nested_includes.patch

File fix_nested_includes.patch, 5.1 kB (added by blweiner, 4 months ago)

fixes nested includes for preloading

  • activerecord/test/schema/schema.rb

    old new  
    2020      t.primary_key :auto_id 
    2121      t.integer     :value 
    2222    end 
     23     
     24    create_table :avatars, :force => true do |t| 
     25      t.integer :picture_id, :null => false 
     26      t.string :filename 
     27      t.string :thumbnail 
     28    end 
     29    add_index :avatars, [:picture_id, :thumbnail], :unique => true 
    2330 
    2431    create_table :binaries, :force => true do |t| 
    2532      t.binary :data 
     
    148155      t.string  :first_name, :null => false 
    149156      t.integer :lock_version, :null => false, :default => 0 
    150157    end 
     158     
     159    create_table :pictures, :force => true do |t| 
     160      t.integer :developer_id, :null => false 
     161      t.string :filename 
     162    end 
     163    add_index :pictures, :developer_id, :unique => true 
    151164 
    152165    create_table :posts, :force => true do |t| 
    153166      t.integer :author_id 
  • activerecord/test/models/developer.rb

    old new  
    4242  has_and_belongs_to_many :special_projects, :join_table => 'developers_projects', :association_foreign_key => 'project_id' 
    4343 
    4444  has_many :audit_logs 
     45   
     46  has_one :picture 
    4547 
    4648  validates_inclusion_of :salary, :in => 50000..200000 
    4749  validates_length_of    :name, :within => 3..20 
  • activerecord/test/cases/associations/eager_test.rb

    old new  
    77require 'models/company' 
    88require 'models/person' 
    99require 'models/reader' 
     10require 'models/developer' 
     11require 'models/picture' 
     12require 'models/avatar' 
    1013 
    1114class EagerAssociationTest < ActiveRecord::TestCase 
    1215  fixtures :posts, :comments, :authors, :categories, :categories_posts, 
    13             :companies, :accounts, :tags, :taggings, :people, :readers 
     16            :companies, :accounts, :tags, :taggings, :people, :readers, :developers 
    1417 
    1518  def test_loading_with_one_association 
    1619    posts = Post.find(:all, :include => :comments) 
     
    371374    post = SpecialPost.find(posts(:thinking).id, :include => :taggings) 
    372375    assert post.taggings.include?(taggings(:thinking_general)) 
    373376  end 
     377   
     378  def test_preload_with_nested_includes 
     379    # none of the developers have a picture, but should still be able to include it 
     380    assert_equal 0, Picture.count 
     381    assert_equal 11, Developer.find(:all, :include => { :picture => :small_avatar }).size 
     382     
     383    # give david a picture 
     384    david = developers(:david) 
     385    assert_difference 'Avatar.count', 2 do 
     386      david.create_picture :filename => 'david.jpg' 
     387    end 
     388     
     389    # now that a developer does have a picture, both pictures and nested association avatar should be preloaded 
     390    assert_equal david.picture.small_avatar, Developer.find(developers(:david).id, :include => { :picture => :small_avatar }).picture.small_avatar 
     391  end 
    374392 
    375393  def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm 
    376394    # Eager includes of has many and habtm associations aren't necessarily sorted in the same way 
  • activerecord/lib/active_record/association_preload.rb

    old new  
    2020            raise "parent must be an association name" unless parent.is_a?(String) || parent.is_a?(Symbol) 
    2121            preload_associations(records, parent, preload_options) 
    2222            reflection = reflections[parent] 
    23             parents = records.map {|record| record.send(reflection.name)}.flatten 
     23            parents = records.map {|record| record.send(reflection.name)}.flatten.compact 
    2424            unless parents.empty? 
    2525              parents.first.class.preload_associations(parents, child) 
    2626            end 
     
    203203          conditions = "#{reflection.klass.table_name}.#{foreign_key} IN (?)" 
    204204        end 
    205205 
    206         conditions << append_conditions(options, preload_options) 
     206        conditions << append_conditions_for_association(reflection, options, preload_options) 
    207207 
    208208        reflection.klass.find(:all, 
    209209                              :select => (options[:select] || "#{table_name}.*"), 
     
    225225        sql << " AND (#{sanitize_sql preload_options[:conditions]})" if preload_options[:conditions] 
    226226        sql 
    227227      end 
     228       
     229      def append_conditions_for_association(reflection, options, preload_options) 
     230        sql = "" 
     231        sql << " AND (#{interpolate_sql_for_preload(reflection.klass.send(:sanitize_sql, options[:conditions]))})" if options[:conditions] 
     232        sql << " AND (#{reflection.klass.send(:sanitize_sql, preload_options[:conditions])})" if preload_options[:conditions] 
     233        sql 
     234      end 
    228235 
    229236    end 
    230237  end