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

Ticket #3438: eager_loading_order_patch_sql_standard.diff

File eager_loading_order_patch_sql_standard.diff, 7.6 kB (added by coda.hale@gmail.com, 2 years ago)

no longer assuming that ordering by primary key is reasonable

  • activerecord/test/associations_cascaded_eager_loading_test.rb

    old new  
    103103      authors.first.posts.first.special_comments.first.post.very_special_comment 
    104104    end 
    105105  end 
     106   
     107  def test_association_orders_work_with_cascaded_eager_loading 
     108    [ { :posts => :comments }, { :posts => :categories }, 
     109      { :posts => [:comments, :categories] }, 
     110      { :comments => :post }, { :funky_comments => :post } ].each do |association| 
     111      regular_records = Author.find(:all).sort_by(&:id) 
     112      eager_records = Author.find(:all, :include => association).sort_by(&:id) 
     113      regular_records.size.times do |i| 
     114        assert_equal regular_records[i].send(association.keys.first).map(&:id), eager_records[i].send(association.keys.first).map(&:id), "Author.#{association.keys.first} has a different order when eagerly loaded via #{association.inspect}." 
     115      end 
     116    end 
     117  end 
    106118end 
  • activerecord/test/associations_go_eager_test.rb

    old new  
    356356    assert_equal 2, one.comments.size 
    357357    assert_equal 2, one.categories.size 
    358358  end 
     359   
     360  def test_association_orders_work_with_eager_loading 
     361    { Author         => [ :posts,  :posts_with_comments, :posts_with_categories, :posts_with_comments_and_categories, 
     362                          :comments, :funky_comments, :special_posts, :hello_posts, :nonexistent_posts,  
     363                          :posts_with_callbacks, :posts_with_proc_callbacks, :posts_with_multiple_callbacks, 
     364                          :unchangable_posts, :author_favorites ], 
     365      Category       => [ :posts, :special_posts, :hello_posts, :nonexistent_posts ], 
     366      DependentFirm  => [ :companies ], 
     367      Firm           => [ :clients, :clients_sorted_desc, :clients_of_firm, :dependent_clients_of_firm, 
     368                          :exclusively_dependent_clients_of_firm, :plain_clients ], 
     369      Person         => [ :readers, :posts ], 
     370      Post           => [ :comments, :special_comments, :categories, :special_categories, :readers, :people ] 
     371    }.each do |model, associations| 
     372      associations.each do |association| 
     373        regular_records = model.find(:all).sort_by(&:id) 
     374        eager_records = model.find(:all, :include => [association]).sort_by(&:id) 
     375        regular_records.size.times do |i| 
     376          assert_equal regular_records[i].send(association).map(&:id), eager_records[i].send(association).map(&:id), "#{model}.#{association} has a different order when eagerly loaded." 
     377        end 
     378         
     379        expected_order = model.find(:all, :order => "#{model.table_name}.#{model.primary_key}").map(&association).flatten.map(&:id) 
     380        actual_order = model.find(:all, :include => [association], :order => "#{model.table_name}.#{model.primary_key}").map(&association).flatten.map(&:id) 
     381        assert_equal expected_order, actual_order, "#{model}.#{association} has a different order when eagerly loaded given an :order option" 
     382      end       
     383    end 
     384  end 
     385 
    359386end 
  • activerecord/test/fixtures/post.rb

    old new  
    1515 
    1616  has_one  :very_special_comment 
    1717  has_one  :very_special_comment_with_post, :class_name => "VerySpecialComment", :include => :post 
    18   has_many :special_comments 
     18  has_many :special_comments, :order => 'type' 
    1919 
    20   has_and_belongs_to_many :categories 
    21   has_and_belongs_to_many :special_categories, :join_table => "categories_posts", :association_foreign_key => 'category_id' 
     20  has_and_belongs_to_many :categories, :order => 'name' 
     21  has_and_belongs_to_many :special_categories, :join_table => "categories_posts", :association_foreign_key => 'category_id', :order => 'name DESC, type ASC' 
    2222 
    2323  has_many :taggings, :as => :taggable 
    2424  has_many :tags, :through => :taggings, :include => :tagging do 
     
    3838  has_many :categorizations, :foreign_key => :category_id 
    3939  has_many :authors, :through => :categorizations 
    4040 
    41   has_many :readers 
    42   has_many :people, :through => :readers 
     41  has_many :readers, :order => 'readers.person_id' 
     42  has_many :people, :through => :readers, :order => 'first_name DESC, id ASC' 
    4343 
    4444  def self.what_are_you 
    4545    'a post...' 
  • activerecord/test/fixtures/author.rb

    old new  
    11class Author < ActiveRecord::Base 
    2   has_many :posts 
    3   has_many :posts_with_comments, :include => :comments, :class_name => "Post" 
    4   has_many :posts_with_categories, :include => :categories, :class_name => "Post" 
     2  has_many :posts, :order => 'title DESC' 
     3  has_many :posts_with_comments, :include => :comments, :class_name => "Post", :order => 'title DESC' 
     4  has_many :posts_with_categories, :include => :categories, :class_name => "Post", :order => 'title' 
    55  has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :order => "posts.id", :class_name => "Post" 
    66  has_many :posts_with_extension, :class_name => "Post" do #, :extend => ProxyTestExtension 
    77    def testing_proxy_owner 
     
    1414      proxy_target 
    1515    end 
    1616  end 
    17   has_many :comments, :through => :posts 
    18   has_many :funky_comments, :through => :posts, :source => :comments 
     17  has_many :comments, :through => :posts, :order => 'body DESC' 
     18  has_many :funky_comments, :through => :posts, :source => :comments, :order => 'body' 
    1919 
    2020  has_many :special_posts,        :class_name => "Post" 
    2121  has_many :hello_posts,          :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'hello'" 
  • activerecord/lib/active_record/associations.rb

    old new  
    11481148          add_limited_ids_condition!(sql, options, join_dependency) if !using_limitable_reflections?(join_dependency.reflections) && ((scope && scope[:limit]) || options[:limit]) 
    11491149 
    11501150          sql << "ORDER BY #{options[:order]} " if options[:order] 
    1151   
     1151           
     1152          # Collect all eagerly-loaded assocations with any order options, and 
     1153          # add in their table names unless it's already there. 
     1154          associated_orders = join_dependency.join_associations.select do |assoc| 
     1155            assoc.reflection.options[:order] 
     1156          end.map do |assoc| 
     1157            orders = assoc.reflection.options[:order].split(',').map(&:strip) 
     1158            orders.map do |order| 
     1159              if order =~ /\./ 
     1160                order 
     1161              else 
     1162                assoc.aliased_table_name + '.' + order 
     1163              end 
     1164            end 
     1165          end 
     1166           
     1167          # Add the association orders to the SQL statement. 
     1168          if associated_orders.any? 
     1169            if options[:order] 
     1170              sql << ", " 
     1171            else 
     1172              sql << "ORDER BY " 
     1173            end 
     1174            sql << associated_orders.flatten.join(', ') 
     1175          end 
     1176          sql << ' ' 
     1177 
    11521178          add_limit!(sql, options, scope) if using_limitable_reflections?(join_dependency.reflections) 
    11531179  
    11541180          return sanitize_sql(sql)