Browse files

Deprecate implicit eager loading. Closes #950.

  • Loading branch information...
1 parent 0b8b682 commit c99d507fccca2e9e4d12e49b4387e007c5481ae9 @jonleighton jonleighton committed Dec 29, 2011
Showing with 181 additions and 99 deletions.
  1. +1 −1 activerecord/lib/active_record/associations/association_scope.rb
  2. +1 −1 activerecord/lib/active_record/associations/builder/association.rb
  3. +1 −0 activerecord/lib/active_record/associations/preloader/association.rb
  4. +1 −0 activerecord/lib/active_record/associations/preloader/through_association.rb
  5. +13 −1 activerecord/lib/active_record/relation.rb
  6. +2 −2 activerecord/lib/active_record/relation/spawn_methods.rb
  7. +26 −6 activerecord/test/cases/associations/cascaded_eager_loading_test.rb
  8. +1 −1 activerecord/test/cases/associations/eager_load_nested_include_test.rb
  9. +42 −42 activerecord/test/cases/associations/eager_test.rb
  10. +2 −2 activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
  11. +1 −1 activerecord/test/cases/associations/has_many_through_associations_test.rb
  12. +3 −3 activerecord/test/cases/associations/has_one_through_associations_test.rb
  13. +1 −1 activerecord/test/cases/associations/inner_join_association_test.rb
  14. +4 −4 activerecord/test/cases/associations/inverse_associations_test.rb
  15. +2 −2 activerecord/test/cases/associations/join_model_test.rb
  16. +2 −2 activerecord/test/cases/associations/nested_through_associations_test.rb
  17. +1 −1 activerecord/test/cases/associations_test.rb
  18. +6 −4 activerecord/test/cases/calculations_test.rb
  19. +3 −3 activerecord/test/cases/finder_test.rb
  20. +33 −9 activerecord/test/cases/method_scoping_test.rb
  21. +1 −1 activerecord/test/cases/modules_test.rb
  22. +2 −2 activerecord/test/cases/relation_scoping_test.rb
  23. +6 −0 activerecord/test/cases/relation_test.rb
  24. +21 −5 activerecord/test/cases/relations_test.rb
  25. +2 −2 activerecord/test/models/author.rb
  26. +1 −1 activerecord/test/models/category.rb
  27. +2 −2 activerecord/test/models/person.rb
View
2 activerecord/lib/active_record/associations/association_scope.rb
@@ -20,7 +20,7 @@ def scope
# It's okay to just apply all these like this. The options will only be present if the
# association supports that option; this is enforced by the association builder.
scope = scope.apply_finder_options(options.slice(
- :readonly, :include, :order, :limit, :joins, :group, :having, :offset, :select))
+ :readonly, :include, :eager_load, :order, :limit, :joins, :group, :having, :offset, :select))
if options[:through] && !options[:include]
scope = scope.includes(source_options[:include])
View
2 activerecord/lib/active_record/associations/builder/association.rb
@@ -1,7 +1,7 @@
module ActiveRecord::Associations::Builder
class Association #:nodoc:
class_attribute :valid_options
- self.valid_options = [:class_name, :foreign_key, :select, :conditions, :include, :extend, :readonly, :validate]
+ self.valid_options = [:class_name, :foreign_key, :select, :conditions, :include, :eager_load, :extend, :readonly, :validate]
# Set by subclasses
class_attribute :macro
View
1 activerecord/lib/active_record/associations/preloader/association.rb
@@ -100,6 +100,7 @@ def build_scope
scope = scope.select(preload_options[:select] || options[:select] || table[Arel.star])
scope = scope.includes(preload_options[:include] || options[:include])
+ scope = scope.eager_load(preload_options[:eager_load] || options[:eager_load])
if options[:as]
scope = scope.where(
View
1 activerecord/lib/active_record/associations/preloader/through_association.rb
@@ -53,6 +53,7 @@ def through_options
else
if options[:conditions]
through_options[:include] = options[:include] || options[:source]
+ through_options[:eager_load] = options[:eager_load] || options[:source]
through_options[:conditions] = options[:conditions]
end
View
14 activerecord/lib/active_record/relation.rb
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
require 'active_support/core_ext/object/blank'
+require 'active_support/deprecation'
module ActiveRecord
# = Active Record Relation
@@ -521,7 +522,18 @@ def references_eager_loaded_tables?
# always convert table names to downcase as in Oracle quoted table names are in uppercase
joined_tables = joined_tables.flatten.compact.map { |t| t.downcase }.uniq
- (tables_in_string(to_sql) - joined_tables).any?
+ referenced_tables = (tables_in_string(to_sql) - joined_tables)
+ if referenced_tables.any?
+ ActiveSupport::Deprecation.warn(
+ "Your query appears to reference tables (#{referenced_tables.join(', ')}) that are not " \
+ "explicitly joined. This implicit joining is deprecated, so you must explicitly " \
+ "reference the tables. For example, instead of Author.includes(:posts).where(\"posts.name = 'foo'\"), " \
+ "you should write Author.eager_load(:posts).where(\"posts.name = 'foo'\")."
+ )
+ true
+ else
+ false
+ end
end
def tables_in_string(string)
View
4 activerecord/lib/active_record/relation/spawn_methods.rb
@@ -113,7 +113,7 @@ def only(*onlies)
result
end
- VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
+ VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend, :eager_load,
:order, :select, :readonly, :group, :having, :from, :lock ]
def apply_finder_options(options)
@@ -124,7 +124,7 @@ def apply_finder_options(options)
finders = options.dup
finders.delete_if { |key, value| value.nil? && key != :limit }
- ([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly] & finders.keys).each do |finder|
+ ([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly, :eager_load] & finders.keys).each do |finder|
relation = relation.send(finder, finders[finder])
end
View
32 activerecord/test/cases/associations/cascaded_eager_loading_test.rb
@@ -61,15 +61,31 @@ def test_cascaded_eager_association_loading_with_join_for_count
end
def test_cascaded_eager_association_loading_with_duplicated_includes
- categories = Category.includes(:categorizations).includes(:categorizations => :author).where("categorizations.id is not null")
+ categories = Category.includes(:categorizations).includes(:categorizations => :author)
+ assert_nothing_raised do
+ assert_equal Category.count, categories.count
+ assert_equal Category.count, categories.all.size
+ end
+ end
+
+ def test_cascaded_eager_association_loading_with_twice_includes_edge_cases
+ categories = Category.includes(:categorizations => :author).includes(:categorizations => :post)
+ assert_nothing_raised do
+ assert_equal Category.count, categories.count
+ assert_equal Category.count, categories.all.size
+ end
+ end
+
+ def test_cascaded_eager_association_loading_with_duplicated_eager_load
+ categories = Category.eager_load(:categorizations).eager_load(:categorizations => :author).where("categorizations.id is not null")
assert_nothing_raised do
assert_equal 3, categories.count
assert_equal 3, categories.all.size
end
end
- def test_cascaded_eager_association_loading_with_twice_includes_edge_cases
- categories = Category.includes(:categorizations => :author).includes(:categorizations => :post).where("posts.id is not null")
+ def test_cascaded_eager_association_loading_with_twice_eager_load_edge_cases
+ categories = Category.eager_load(:categorizations => :author).eager_load(:categorizations => :post).where("posts.id is not null")
assert_nothing_raised do
assert_equal 3, categories.count
assert_equal 3, categories.all.size
@@ -127,7 +143,7 @@ def test_eager_association_loading_with_has_many_sti_and_subclasses
silly.parent_id = 1
assert silly.save
- topics = Topic.find(:all, :include => :replies, :order => 'topics.id, replies_topics.id')
+ topics = Topic.eager_load(:replies).order('topics.id, replies_topics.id').to_a
assert_no_queries do
assert_equal 2, topics[0].replies.size
assert_equal 0, topics[1].replies.size
@@ -142,7 +158,9 @@ def test_eager_association_loading_with_belongs_to_sti
end
def test_eager_association_loading_with_multiple_stis_and_order
- author = Author.find(:first, :include => { :posts => [ :special_comments , :very_special_comment ] }, :order => ['authors.name', 'comments.body', 'very_special_comments_posts.body'], :conditions => 'posts.id = 4')
+ author = Author.eager_load(:posts => [ :special_comments , :very_special_comment ]).
+ order('authors.name', 'comments.body', 'very_special_comments_posts.body').
+ where('posts.id = 4').first
assert_equal authors(:david), author
assert_no_queries do
author.posts.first.special_comments
@@ -151,7 +169,9 @@ def test_eager_association_loading_with_multiple_stis_and_order
end
def test_eager_association_loading_of_stis_with_multiple_references
- authors = Author.find(:all, :include => { :posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } } }, :order => 'comments.body, very_special_comments_posts.body', :conditions => 'posts.id = 4')
+ authors = Author.eager_load(:posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } }).
+ order('comments.body, very_special_comments_posts.body').
+ where('posts.id = 4')
assert_equal [authors(:david)], authors
assert_no_queries do
authors.first.posts.first.special_comments.first.post.special_comments
View
2 activerecord/test/cases/associations/eager_load_nested_include_test.rb
@@ -123,7 +123,7 @@ def test_missing_data_in_a_nested_include_should_not_cause_errors_when_construct
assert_nothing_raised do
# @davey_mcdave doesn't have any author_favorites
includes = {:posts => :comments, :categorizations => :category, :author_favorites => :favorite_author }
- Author.all :include => includes, :conditions => {:authors => {:name => @davey_mcdave.name}}, :order => 'categories.name'
+ Author.all :eager_load => includes, :conditions => {:authors => {:name => @davey_mcdave.name}}, :order => 'categories.name'
end
end
end
View
84 activerecord/test/cases/associations/eager_test.rb
@@ -55,13 +55,13 @@ def test_loading_with_one_association
end
def test_loading_with_one_association_with_non_preload
- posts = Post.find(:all, :include => :last_comment, :order => 'comments.id DESC')
+ posts = Post.find(:all, :eager_load => :last_comment, :order => 'comments.id DESC')
post = posts.find { |p| p.id == 1 }
assert_equal Post.find(1).last_comment, post.last_comment
end
def test_loading_conditions_with_or
- posts = authors(:david).posts.find(:all, :include => :comments, :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'")
+ posts = authors(:david).posts.find(:all, :eager_load => :comments, :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'")
assert_nil posts.detect { |p| p.author_id != authors(:david).id },
"expected to find only david's posts"
end
@@ -165,7 +165,7 @@ def test_including_duplicate_objects_from_has_many
comment = car_post.comments.create!(:body => "hmm")
categories = Category.find(:all, :conditions => ["posts.id=?", car_post.id],
- :include => {:posts => :comments})
+ :eager_load => {:posts => :comments})
categories.each do |category|
assert_equal [comment], category.posts[0].comments
end
@@ -263,12 +263,12 @@ def test_nested_loading_through_has_one_association_with_order
end
def test_nested_loading_through_has_one_association_with_order_on_association
- aa = AuthorAddress.find(author_addresses(:david_address).id, :include => {:author => :posts}, :order => 'authors.id')
+ aa = AuthorAddress.find(author_addresses(:david_address).id, :eager_load => {:author => :posts}, :order => 'authors.id')
assert_equal aa.author.posts.count, aa.author.posts.length
end
def test_nested_loading_through_has_one_association_with_order_on_nested_association
- aa = AuthorAddress.find(author_addresses(:david_address).id, :include => {:author => :posts}, :order => 'posts.id')
+ aa = AuthorAddress.find(author_addresses(:david_address).id, :eager_load => {:author => :posts}, :order => 'posts.id')
assert_equal aa.author.posts.count, aa.author.posts.length
end
@@ -278,12 +278,12 @@ def test_nested_loading_through_has_one_association_with_conditions
end
def test_nested_loading_through_has_one_association_with_conditions_on_association
- aa = AuthorAddress.find(author_addresses(:david_address).id, :include => {:author => :posts}, :conditions => "authors.id > 0")
+ aa = AuthorAddress.find(author_addresses(:david_address).id, :eager_load => {:author => :posts}, :conditions => "authors.id > 0")
assert_equal aa.author.posts.count, aa.author.posts.length
end
def test_nested_loading_through_has_one_association_with_conditions_on_nested_association
- aa = AuthorAddress.find(author_addresses(:david_address).id, :include => {:author => :posts}, :conditions => "posts.id > 0")
+ aa = AuthorAddress.find(author_addresses(:david_address).id, :eager_load => {:author => :posts}, :conditions => "posts.id > 0")
assert_equal aa.author.posts.count, aa.author.posts.length
end
@@ -332,14 +332,14 @@ def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_cond
def test_eager_association_loading_with_belongs_to_and_conditions_string_with_unquoted_table_name
assert_nothing_raised do
- Comment.find(:all, :include => :post, :conditions => ['posts.id = ?',4])
+ Comment.eager_load(:post).where('posts.id = ?',4).to_a
end
end
def test_eager_association_loading_with_belongs_to_and_conditions_hash
comments = []
assert_nothing_raised do
- comments = Comment.find(:all, :include => :post, :conditions => {:posts => {:id => 4}}, :limit => 3, :order => 'comments.id')
+ comments = Comment.eager_load(:post).where(:posts => {:id => 4}).limit(3).order('comments.id').to_a
end
assert_equal 3, comments.length
assert_equal [5,6,7], comments.collect { |c| c.id }
@@ -351,20 +351,20 @@ def test_eager_association_loading_with_belongs_to_and_conditions_hash
def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
assert_nothing_raised do
- Comment.find(:all, :include => :post, :conditions => ["#{quoted_posts_id} = ?",4])
+ Comment.eager_load(:post).where("#{quoted_posts_id} = ?",4).to_a
end
end
def test_eager_association_loading_with_belongs_to_and_order_string_with_unquoted_table_name
assert_nothing_raised do
- Comment.find(:all, :include => :post, :order => 'posts.id')
+ Comment.eager_load(:post).order('posts.id').to_a
end
end
def test_eager_association_loading_with_belongs_to_and_order_string_with_quoted_table_name
quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
assert_nothing_raised do
- Comment.find(:all, :include => :post, :order => quoted_posts_id)
+ Comment.eager_load(:post).order(quoted_posts_id).to_a
end
end
@@ -528,36 +528,36 @@ def test_eager_with_has_many_and_limit_and_conditions_array
end
def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers
- posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
+ posts = Post.find(:all, :eager_load => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
assert_equal 2, posts.size
- count = Post.count(:include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
+ count = Post.count(:eager_load => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
assert_equal count, posts.size
end
def test_eager_with_has_many_and_limit_and_high_offset
- posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
+ posts = Post.find(:all, :eager_load => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
assert_equal 0, posts.size
end
def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_array_conditions
assert_queries(1) do
- posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10,
+ posts = Post.find(:all, :eager_load => [ :author, :comments ], :limit => 2, :offset => 10,
:conditions => [ "authors.name = ? and comments.body = ?", 'David', 'go crazy' ])
assert_equal 0, posts.size
end
end
def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_hash_conditions
assert_queries(1) do
- posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10,
+ posts = Post.find(:all, :eager_load => [ :author, :comments ], :limit => 2, :offset => 10,
:conditions => { 'authors.name' => 'David', 'comments.body' => 'go crazy' })
assert_equal 0, posts.size
end
end
def test_count_eager_with_has_many_and_limit_and_high_offset
- posts = Post.count(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
+ posts = Post.eager_load(:author, :comments).limit(2).offset(10).where("authors.name = ?", 'David').count
assert_equal 0, posts
end
@@ -569,7 +569,7 @@ def test_eager_with_has_many_and_limit_with_no_results
def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional
author = authors(:david)
author_posts_without_comments = author.posts.select { |post| post.comments.blank? }
- assert_equal author_posts_without_comments.size, author.posts.count(:all, :include => :comments, :conditions => 'comments.id is null')
+ assert_equal author_posts_without_comments.size, author.posts.eager_load(:comments).where('comments.id is null').count
end
def test_eager_count_performed_on_a_has_many_through_association_with_multi_table_conditional
@@ -606,14 +606,14 @@ def test_has_and_belongs_to_many_should_not_instantiate_same_records_multiple_ti
def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers
posts = authors(:david).posts.find(:all,
- :include => :comments,
+ :eager_load => :comments,
:conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'",
:limit => 2
)
assert_equal 2, posts.size
count = Post.count(
- :include => [ :comments, :author ],
+ :eager_load => [ :comments, :author ],
:conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')",
:limit => 2
)
@@ -623,15 +623,15 @@ def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers
def test_eager_with_has_many_and_limit_and_scoped_conditions_on_the_eagers
posts = nil
Post.send(:with_scope, :find => {
- :include => :comments,
+ :eager_load => :comments,
:conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'"
}) do
posts = authors(:david).posts.find(:all, :limit => 2)
assert_equal 2, posts.size
end
Post.send(:with_scope, :find => {
- :include => [ :comments, :author ],
+ :eager_load => [ :comments, :author ],
:conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')"
}) do
count = Post.count(:limit => 2)
@@ -642,14 +642,14 @@ def test_eager_with_has_many_and_limit_and_scoped_conditions_on_the_eagers
def test_eager_with_has_many_and_limit_and_scoped_and_explicit_conditions_on_the_eagers
Post.send(:with_scope, :find => { :conditions => "1=1" }) do
posts = authors(:david).posts.find(:all,
- :include => :comments,
+ :eager_load => :comments,
:conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'",
:limit => 2
)
assert_equal 2, posts.size
count = Post.count(
- :include => [ :comments, :author ],
+ :eager_load => [ :comments, :author ],
:conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')",
:limit => 2
)
@@ -658,9 +658,9 @@ def test_eager_with_has_many_and_limit_and_scoped_and_explicit_conditions_on_the
end
def test_eager_with_scoped_order_using_association_limiting_without_explicit_scope
- posts_with_explicit_order = Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :order => 'posts.id DESC', :limit => 2)
+ posts_with_explicit_order = Post.find(:all, :conditions => 'comments.id is not null', :eager_load => :comments, :order => 'posts.id DESC', :limit => 2)
posts_with_scoped_order = Post.send(:with_scope, :find => {:order => 'posts.id DESC'}) do
- Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :limit => 2)
+ Post.find(:all, :conditions => 'comments.id is not null', :eager_load => :comments, :limit => 2)
end
assert_equal posts_with_explicit_order, posts_with_scoped_order
end
@@ -773,17 +773,17 @@ def find_all_ordered(className, include=nil)
end
def test_limited_eager_with_order
- assert_equal posts(:thinking, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title)', :limit => 2, :offset => 1)
- assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC', :limit => 2, :offset => 1)
+ assert_equal posts(:thinking, :sti_comments), Post.find(:all, :eager_load => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title)', :limit => 2, :offset => 1)
+ assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :eager_load => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC', :limit => 2, :offset => 1)
end
def test_limited_eager_with_multiple_order_columns
- assert_equal posts(:thinking, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => ['UPPER(posts.title)', 'posts.id'], :limit => 2, :offset => 1)
- assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => ['UPPER(posts.title) DESC', 'posts.id'], :limit => 2, :offset => 1)
+ assert_equal posts(:thinking, :sti_comments), Post.find(:all, :eager_load => [:author, :comments], :conditions => "authors.name = 'David'", :order => ['UPPER(posts.title)', 'posts.id'], :limit => 2, :offset => 1)
+ assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :eager_load => [:author, :comments], :conditions => "authors.name = 'David'", :order => ['UPPER(posts.title) DESC', 'posts.id'], :limit => 2, :offset => 1)
end
def test_limited_eager_with_numeric_in_association
- assert_equal people(:david, :susan), Person.find(:all, :include => [:readers, :primary_contact, :number1_fan], :conditions => "number1_fans_people.first_name like 'M%'", :order => 'people.id', :limit => 2, :offset => 0)
+ assert_equal people(:david, :susan), Person.find(:all, :eager_load => [:readers, :primary_contact, :number1_fan], :conditions => "number1_fans_people.first_name like 'M%'", :order => 'people.id', :limit => 2, :offset => 0)
end
def test_preload_with_interpolation
@@ -898,11 +898,11 @@ def test_preconfigured_includes_with_has_many_and_habtm
def test_count_with_include
if current_adapter?(:SybaseAdapter)
- assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "len(comments.body) > 15")
+ assert_equal 3, assert_deprecated { authors(:david).posts_with_comments.count(:conditions => "len(comments.body) > 15") }
elsif current_adapter?(:OpenBaseAdapter)
- assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(FETCHBLOB(comments.body)) > 15")
+ assert_equal 3, assert_deprecated { authors(:david).posts_with_comments.count(:conditions => "length(FETCHBLOB(comments.body)) > 15") }
else
- assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(comments.body) > 15")
+ assert_equal 3, assert_deprecated { authors(:david).posts_with_comments.count(:conditions => "length(comments.body) > 15") }
end
end
@@ -913,11 +913,11 @@ def test_load_with_sti_sharing_association
end
def test_conditions_on_join_table_with_include_and_limit
- assert_equal 3, Developer.find(:all, :include => 'projects', :conditions => 'developers_projects.access_level = 1', :limit => 5).size
+ assert_equal 3, assert_deprecated { Developer.find(:all, :include => 'projects', :conditions => 'developers_projects.access_level = 1', :limit => 5).size }
end
def test_order_on_join_table_with_include_and_limit
- assert_equal 5, Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size
+ assert_equal 5, assert_deprecated { Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size }
end
def test_eager_loading_with_order_on_joined_table_preloads
@@ -1014,9 +1014,9 @@ def test_include_has_many_using_primary_key
expected = Firm.find(1).clients_using_primary_key.sort_by(&:name)
# Oracle adapter truncates alias to 30 characters
if current_adapter?(:OracleAdapter)
- firm = Firm.find 1, :include => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies'[0,30]+'.name'
+ firm = Firm.find 1, :eager_load => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies'[0,30]+'.name'
else
- firm = Firm.find 1, :include => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name'
+ firm = Firm.find 1, :eager_load => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name'
end
assert_no_queries do
assert_equal expected, firm.clients_using_primary_key
@@ -1033,7 +1033,7 @@ def test_preload_has_one_using_primary_key
def test_include_has_one_using_primary_key
expected = accounts(:signals37)
- firm = Firm.find(:all, :include => :account_using_primary_key, :order => 'accounts.id').detect {|f| f.id == 1}
+ firm = Firm.find(:all, :eager_load => :account_using_primary_key, :order => 'accounts.id').detect {|f| f.id == 1}
assert_no_queries do
assert_equal expected, firm.account_using_primary_key
end
@@ -1086,13 +1086,13 @@ def test_joins_with_includes_should_preload_via_joins
def test_join_eager_with_empty_order_should_generate_valid_sql
assert_nothing_raised(ActiveRecord::StatementInvalid) do
- Post.includes(:comments).order("").where(:comments => {:body => "Thank you for the welcome"}).first
+ Post.eager_load(:comments).order("").where(:comments => {:body => "Thank you for the welcome"}).first
end
end
def test_join_eager_with_nil_order_should_generate_valid_sql
assert_nothing_raised(ActiveRecord::StatementInvalid) do
- Post.includes(:comments).order(nil).where(:comments => {:body => "Thank you for the welcome"}).first
+ Post.eager_load(:comments).order(nil).where(:comments => {:body => "Thank you for the welcome"}).first
end
end
View
4 activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
@@ -679,7 +679,7 @@ def test_habtm_respects_select_query_method
end
def test_join_table_alias
- assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
+ assert_equal 3, Developer.find(:all, :eager_load => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
end
def test_join_with_group
@@ -689,7 +689,7 @@ def test_join_with_group
end
Project.columns.each { |c| group << "projects.#{c.name}" }
- assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
+ assert_equal 3, Developer.find(:all, :eager_load => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
end
def test_find_grouped
View
2 activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -847,7 +847,7 @@ def test_create_bang_returns_falsy_when_join_record_has_errors
def test_preloading_empty_through_association_via_joins
person = Person.create!(:first_name => "Gaga")
- person = Person.where(:id => person.id).where('readers.id = 1 or 1=1').includes(:posts).to_a.first
+ person = Person.where(:id => person.id).where('readers.id = 1 or 1=1').eager_load(:posts).to_a.first
assert person.posts.loaded?, 'person.posts should be loaded'
assert_equal [], person.posts
View
6 activerecord/test/cases/associations/has_one_through_associations_test.rb
@@ -111,15 +111,15 @@ def test_eager_has_one_through_polymorphic_with_source_type
def test_has_one_through_nonpreload_eagerloading
members = assert_queries(1) do
- Member.find(:all, :include => :club, :conditions => ["members.name = ?", "Groucho Marx"], :order => 'clubs.name') #force fallback
+ Member.find(:all, :eager_load => :club, :conditions => ["members.name = ?", "Groucho Marx"], :order => 'clubs.name') #force fallback
end
assert_equal 1, members.size
assert_not_nil assert_no_queries {members[0].club}
end
def test_has_one_through_nonpreload_eager_loading_through_polymorphic
members = assert_queries(1) do
- Member.find(:all, :include => :sponsor_club, :conditions => ["members.name = ?", "Groucho Marx"], :order => 'clubs.name') #force fallback
+ Member.find(:all, :eager_load => :sponsor_club, :conditions => ["members.name = ?", "Groucho Marx"], :order => 'clubs.name') #force fallback
end
assert_equal 1, members.size
assert_not_nil assert_no_queries {members[0].sponsor_club}
@@ -128,7 +128,7 @@ def test_has_one_through_nonpreload_eager_loading_through_polymorphic
def test_has_one_through_nonpreload_eager_loading_through_polymorphic_with_more_than_one_through_record
Sponsor.new(:sponsor_club => clubs(:crazy_club), :sponsorable => members(:groucho)).save!
members = assert_queries(1) do
- Member.find(:all, :include => :sponsor_club, :conditions => ["members.name = ?", "Groucho Marx"], :order => 'clubs.name DESC') #force fallback
+ Member.find(:all, :eager_load => :sponsor_club, :conditions => ["members.name = ?", "Groucho Marx"], :order => 'clubs.name DESC') #force fallback
end
assert_equal 1, members.size
assert_not_nil assert_no_queries { members[0].sponsor_club }
View
2 activerecord/test/cases/associations/inner_join_association_test.rb
@@ -42,7 +42,7 @@ def test_join_conditions_added_to_join_clause
end
def test_join_conditions_allow_nil_associations
- authors = Author.includes(:essays).where(:essays => {:id => nil})
+ authors = Author.eager_load(:essays).where(:essays => {:id => nil})
assert_equal 2, authors.count
end
View
8 activerecord/test/cases/associations/inverse_associations_test.rb
@@ -104,7 +104,7 @@ def test_parent_instance_should_be_shared_with_eager_loaded_child_on_find
f.man.name = 'Mungo'
assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
- m = Man.find(:first, :conditions => {:name => 'Gordon'}, :include => :face, :order => 'faces.id')
+ m = Man.find(:first, :conditions => {:name => 'Gordon'}, :eager_load => :face, :order => 'faces.id')
f = m.face
assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
m.name = 'Bongo'
@@ -189,7 +189,7 @@ def test_parent_instance_should_be_shared_with_eager_loaded_children
assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
end
- m = Man.find(:first, :conditions => {:name => 'Gordon'}, :include => :interests, :order => 'interests.id')
+ m = Man.find(:first, :conditions => {:name => 'Gordon'}, :eager_load => :interests, :order => 'interests.id')
is = m.interests
is.each do |i|
assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
@@ -286,7 +286,7 @@ def test_eager_loaded_child_instance_should_be_shared_with_parent_on_find
m.face.description = 'pleasing'
assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
- f = Face.find(:first, :include => :man, :order => 'men.id', :conditions => {:description => 'trusting'})
+ f = Face.find(:first, :eager_load => :man, :order => 'men.id', :conditions => {:description => 'trusting'})
m = f.man
assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
f.description = 'gormless'
@@ -369,7 +369,7 @@ def test_eager_loaded_child_instance_should_be_shared_with_parent_on_find
m.polymorphic_face.description = 'pleasing'
assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same after changes to parent-owned instance"
- f = Face.find(:first, :conditions => {:description => 'confused'}, :include => :man, :order => 'men.id')
+ f = Face.find(:first, :conditions => {:description => 'confused'}, :eager_load => :man, :order => 'men.id')
m = f.polymorphic_man
assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same before changes to child instance"
f.description = 'gormless'
View
4 activerecord/test/cases/associations/join_model_test.rb
@@ -362,7 +362,7 @@ def test_has_many_polymorphic
end
assert_raise ActiveRecord::EagerLoadPolymorphicError do
- tags(:general).taggings.find(:all, :include => :taggable, :conditions => 'bogus_table.column = 1')
+ tags(:general).taggings.eager_load(:taggable).where('bogus_table.column = 1').to_a
end
end
@@ -419,7 +419,7 @@ def test_include_has_many_through_polymorphic_has_many
end
def test_eager_load_has_many_through_has_many
- author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id'
+ author = Author.where('name = ?', 'David').eager_load(:comments).order('comments.id').first
SpecialComment.new; VerySpecialComment.new
assert_no_queries do
assert_equal [1,2,3,5,6,7,8,9,10,12], author.comments.collect(&:id)
View
4 activerecord/test/cases/associations/nested_through_associations_test.rb
@@ -515,7 +515,7 @@ def test_nested_has_many_through_with_conditions_on_source_associations
end
def test_nested_has_many_through_with_conditions_on_source_associations_preload
- authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a.sort_by(&:id) }
+ authors = assert_queries(2) { Author.includes(:misc_post_first_blue_tags_2).to_a.sort_by(&:id) }
blue = tags(:blue)
assert_no_queries do
@@ -560,7 +560,7 @@ def assert_includes_and_joins_equal(query, expected, association)
actual = assert_queries(1) { query.joins(association).to_a.uniq }
assert_equal expected, actual
- actual = assert_queries(1) { query.includes(association).to_a.uniq }
+ actual = assert_queries(1) { query.eager_load(association).to_a.uniq }
assert_equal expected, actual
end
end
View
2 activerecord/test/cases/associations_test.rb
@@ -29,7 +29,7 @@ def test_eager_loading_should_not_change_count_of_children
molecule.electrons.create(:name => 'electron_1')
molecule.electrons.create(:name => 'electron_2')
- liquids = Liquid.includes(:molecules => :electrons).where('molecules.id is not null')
+ liquids = Liquid.eager_load(:molecules => :electrons).where('molecules.id is not null')
assert_equal 1, liquids[0].molecules.length
end
View
10 activerecord/test/cases/calculations_test.rb
@@ -49,11 +49,11 @@ def test_should_get_maximum_of_field
end
def test_should_get_maximum_of_field_with_include
- assert_equal 55, Account.maximum(:credit_limit, :include => :firm, :conditions => "companies.name != 'Summit'")
+ assert_equal 55, Account.eager_load(:firm).where("companies.name != 'Summit'").maximum(:credit_limit)
end
def test_should_get_maximum_of_field_with_scoped_include
- Account.send :with_scope, :find => { :include => :firm, :conditions => "companies.name != 'Summit'" } do
+ Account.eager_load(:firm).where("companies.name != 'Summit'").scoping do
assert_equal 55, Account.maximum(:credit_limit)
end
end
@@ -270,7 +270,7 @@ def test_should_calculate_grouped_association_with_foreign_key_option
end
def test_should_not_modify_options_when_using_includes
- options = {:conditions => 'companies.id > 1', :include => :firm}
+ options = {:include => :firm}
options_copy = options.dup
Account.count(:all, options)
@@ -334,7 +334,9 @@ def test_should_not_perform_joined_include_by_default
end
def test_should_perform_joined_include_when_referencing_included_tables
- joined_count = Account.includes(:firm).where(:companies => {:name => '37signals'}).count
+ joined_count = assert_deprecated do
+ Account.includes(:firm).where(:companies => {:name => '37signals'}).count
+ end
assert_equal 1, joined_count
end
View
6 activerecord/test/cases/finder_test.rb
@@ -1119,9 +1119,9 @@ def test_select_rows
end
def test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
- assert_equal 2, Post.find(:all, :include => { :authors => :author_address }, :order => ' author_addresses.id DESC ', :limit => 2).size
+ assert_equal 2, Post.find(:all, :eager_load => { :authors => :author_address }, :order => ' author_addresses.id DESC ', :limit => 2).size
- assert_equal 3, Post.find(:all, :include => { :author => :author_address, :authors => :author_address},
+ assert_equal 3, Post.find(:all, :eager_load => { :author => :author_address, :authors => :author_address},
:order => ' author_addresses_authors.id DESC ', :limit => 3).size
end
@@ -1149,7 +1149,7 @@ def test_find_with_nil_inside_set_passed_for_attribute
end
def test_with_limiting_with_custom_select
- posts = Post.find(:all, :include => :author, :select => ' posts.*, authors.id as "author_id"', :limit => 3, :order => 'posts.id')
+ posts = Post.find(:all, :eager_load => :author, :select => ' posts.*, authors.id as "author_id"', :limit => 3, :order => 'posts.id')
assert_equal 3, posts.size
assert_equal [0, 1, 1], posts.map(&:author_id).sort
end
View
42 activerecord/test/cases/method_scoping_test.rb
@@ -103,7 +103,7 @@ def test_scoped_count
def test_scoped_find_include
# with the include, will retrieve only developers for the given project
- scoped_developers = Developer.send(:with_scope, :find => { :include => :projects }) do
+ scoped_developers = Developer.send(:with_scope, :find => { :eager_load => :projects }) do
Developer.find(:all, :conditions => 'projects.id = 2')
end
assert scoped_developers.include?(developers(:david))
@@ -203,7 +203,7 @@ def test_scoped_find_strips_spaces_from_string_joins_and_eliminates_duplicate_st
def test_scoped_count_include
# with the include, will retrieve only developers for the given project
- Developer.send(:with_scope, :find => { :include => :projects }) do
+ Developer.send(:with_scope, :find => { :eager_load => :projects }) do
assert_equal 1, Developer.count(:conditions => 'projects.id = 2')
end
end
@@ -268,7 +268,7 @@ def test_ensure_that_method_scoping_is_correctly_restored
end
class NestedScopingTest < ActiveRecord::TestCase
- fixtures :authors, :developers, :projects, :comments, :posts
+ fixtures :authors, :developers, :projects, :comments, :posts, :developers_projects
def test_merge_options
Developer.send(:with_scope, :find => { :conditions => 'salary = 80000' }) do
@@ -338,7 +338,7 @@ def test_nested_scoped_find
end
def test_nested_scoped_find_include
- Developer.send(:with_scope, :find => { :include => :projects }) do
+ Developer.send(:with_scope, :find => { :eager_load => :projects }) do
Developer.send(:with_scope, :find => { :conditions => "projects.id = 2" }) do
assert_nothing_raised { Developer.find(1) }
assert_equal('David', Developer.find(:first).name)
@@ -350,23 +350,47 @@ def test_nested_scoped_find_merged_include
# :include's remain unique and don't "double up" when merging
Developer.send(:with_scope, :find => { :include => :projects, :conditions => "projects.id = 2" }) do
Developer.send(:with_scope, :find => { :include => :projects }) do
- assert_equal 1, Developer.scoped.includes_values.uniq.length
- assert_equal 'David', Developer.find(:first).name
+ assert_deprecated do
+ assert_equal 1, Developer.scoped.includes_values.uniq.length
+ assert_equal 'David', Developer.find(:first).name
+ end
end
end
# the nested scope doesn't remove the first :include
Developer.send(:with_scope, :find => { :include => :projects, :conditions => "projects.id = 2" }) do
Developer.send(:with_scope, :find => { :include => [] }) do
- assert_equal 1, Developer.scoped.includes_values.uniq.length
- assert_equal('David', Developer.find(:first).name)
+ assert_deprecated do
+ assert_equal 1, Developer.scoped.includes_values.uniq.length
+ assert_equal('David', Developer.find(:first).name)
+ end
end
end
# mixing array and symbol include's will merge correctly
Developer.send(:with_scope, :find => { :include => [:projects], :conditions => "projects.id = 2" }) do
Developer.send(:with_scope, :find => { :include => :projects }) do
- assert_equal 1, Developer.scoped.includes_values.uniq.length
+ assert_deprecated do
+ assert_equal 1, Developer.scoped.includes_values.uniq.length
+ assert_equal('David', Developer.find(:first).name)
+ end
+ end
+ end
+ end
+
+ def test_nested_scoped_find_merged_eager_load
+ # :include's remain unique and don't "double up" when merging
+ Developer.send(:with_scope, :find => { :eager_load => :projects, :conditions => "projects.id = 2" }) do
+ Developer.send(:with_scope, :find => { :eager_load => :projects }) do
+ assert_equal 1, Developer.scoped.eager_load_values.uniq.length
+ assert_equal 'David', Developer.find(:first).name
+ end
+ end
+
+ # mixing array and symbol include's will merge correctly
+ Developer.send(:with_scope, :find => { :eager_load => [:projects], :conditions => "projects.id = 2" }) do
+ Developer.send(:with_scope, :find => { :eager_load => :projects }) do
+ assert_equal 1, Developer.scoped.eager_load_values.uniq.length
assert_equal('David', Developer.find(:first).name)
end
end
View
2 activerecord/test/cases/modules_test.rb
@@ -72,7 +72,7 @@ def test_eager_loading_in_modules
clients = []
assert_nothing_raised NameError, "Should be able to resolve all class constants via reflection" do
- clients << MyApplication::Business::Client.find(3, :include => {:firm => :account}, :conditions => 'accounts.id IS NOT NULL')
+ clients << MyApplication::Business::Client.find(3, :eager_load => {:firm => :account}, :conditions => 'accounts.id IS NOT NULL')
clients << MyApplication::Business::Client.find(3, :include => {:firm => :account})
end
View
4 activerecord/test/cases/relation_scoping_test.rb
@@ -105,7 +105,7 @@ def test_scoped_count
def test_scoped_find_include
# with the include, will retrieve only developers for the given project
- scoped_developers = Developer.includes(:projects).scoping do
+ scoped_developers = Developer.eager_load(:projects).scoping do
Developer.where('projects.id = 2').all
end
assert scoped_developers.include?(developers(:david))
@@ -522,7 +522,7 @@ def test_default_scope_include_with_count
d = DeveloperWithIncludes.create!
d.audit_logs.create! :message => 'foo'
- assert_equal 1, DeveloperWithIncludes.where(:audit_logs => { :message => 'foo' }).count
+ assert_equal 1, DeveloperWithIncludes.eager_load(:audit_logs).where(:audit_logs => { :message => 'foo' }).count
end
def test_default_scope_is_threadsafe
View
6 activerecord/test/cases/relation_test.rb
@@ -135,5 +135,11 @@ def test_eager_load_values
relation.eager_load_values << :b
assert relation.eager_loading?
end
+
+ def test_apply_finder_options_supports_eager_load
+ relation = Relation.new :a, :b
+ relation = relation.apply_finder_options(:eager_load => :b)
+ assert_equal [:b], relation.eager_load_values
+ end
end
end
View
26 activerecord/test/cases/relations_test.rb
@@ -16,7 +16,6 @@
require 'models/tyre'
require 'models/minivan'
-
class RelationTest < ActiveRecord::TestCase
fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
:tags, :taggings, :cars, :minivans
@@ -177,19 +176,19 @@ def test_finding_with_order_and_take
end
def test_finding_with_cross_table_order_and_limit
- tags = Tag.includes(:taggings).
+ tags = Tag.eager_load(:taggings).
order("tags.name asc", "taggings.taggable_id asc", "REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").
limit(1).to_a
assert_equal 1, tags.length
end
def test_finding_with_complex_order_and_limit
- tags = Tag.includes(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").limit(1).to_a
+ tags = Tag.eager_load(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").limit(1).to_a
assert_equal 1, tags.length
end
def test_finding_with_complex_order
- tags = Tag.includes(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").to_a
+ tags = Tag.eager_load(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").to_a
assert_equal 3, tags.length
end
@@ -1104,7 +1103,9 @@ def test_eager_loading_with_conditions_on_joins
)
)
- assert scope.eager_loading?
+ assert_deprecated do
+ assert scope.eager_loading?
+ end
end
def test_ordering_with_extra_spaces
@@ -1164,4 +1165,19 @@ def test_uniq
end
assert_equal ['Foo', 'Foo'], query.uniq(true).uniq(false).map(&:name)
end
+
+ def test_deprecated_references_eager_loaded_tables
+ expected = tags(:general)
+ tagging = taggings(:welcome_general)
+ tag = assert_queries 1 do
+ assert_deprecated do
+ Tag.includes(:taggings).where(:taggings => { :id => tagging.id }).to_a.first
+ end
+ end
+
+ assert_equal expected, tag
+ assert_no_queries do
+ tag.taggings.to_a
+ end
+ end
end
View
4 activerecord/test/models/author.rb
@@ -3,7 +3,7 @@ class Author < ActiveRecord::Base
has_many :very_special_comments, :through => :posts
has_many :posts_with_comments, :include => :comments, :class_name => "Post"
has_many :popular_grouped_posts, :include => :comments, :class_name => "Post", :group => "type", :having => "SUM(comments_count) > 1", :select => "type"
- has_many :posts_with_comments_sorted_by_comment_id, :include => :comments, :class_name => "Post", :order => 'comments.id'
+ has_many :posts_with_comments_sorted_by_comment_id, :eager_load => :comments, :class_name => "Post", :order => 'comments.id'
has_many :posts_sorted_by_id_limited, :class_name => "Post", :order => 'posts.id', :limit => 1
has_many :posts_with_categories, :include => :categories, :class_name => "Post"
has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :order => "posts.id", :class_name => "Post"
@@ -54,7 +54,7 @@ def testing_proxy_target
has_many :hello_posts, :class_name => "Post", :conditions => "posts.body = 'hello'"
has_many :hello_post_comments, :through => :hello_posts, :source => :comments
- has_many :posts_with_no_comments, :class_name => 'Post', :conditions => 'comments.id is null', :include => :comments
+ has_many :posts_with_no_comments, :class_name => 'Post', :conditions => 'comments.id is null', :eager_load => :comments
has_many :hello_posts_with_hash_conditions, :class_name => "Post",
:conditions => {:body => 'hello'}
View
2 activerecord/test/models/category.rb
@@ -2,7 +2,7 @@ class Category < ActiveRecord::Base
has_and_belongs_to_many :posts
has_and_belongs_to_many :special_posts, :class_name => "Post"
has_and_belongs_to_many :other_posts, :class_name => "Post"
- has_and_belongs_to_many :posts_with_authors_sorted_by_author_id, :class_name => "Post", :include => :authors, :order => "authors.id"
+ has_and_belongs_to_many :posts_with_authors_sorted_by_author_id, :class_name => "Post", :eager_load => :authors, :order => "authors.id"
has_and_belongs_to_many(:select_testing_posts,
:class_name => 'Post',
View
4 activerecord/test/models/person.rb
@@ -3,13 +3,13 @@ class Person < ActiveRecord::Base
has_one :reader
has_many :posts, :through => :readers
- has_many :posts_with_no_comments, :through => :readers, :source => :post, :include => :comments, :conditions => 'comments.id is null'
+ has_many :posts_with_no_comments, :through => :readers, :source => :post, :eager_load => :comments, :conditions => 'comments.id is null'
has_many :references
has_many :bad_references
has_many :fixed_bad_references, :conditions => { :favourite => true }, :class_name => 'BadReference'
has_one :favourite_reference, :class_name => 'Reference', :conditions => ['favourite=?', true]
- has_many :posts_with_comments_sorted_by_comment_id, :through => :readers, :source => :post, :include => :comments, :order => 'comments.id'
+ has_many :posts_with_comments_sorted_by_comment_id, :through => :readers, :source => :post, :eager_load => :comments, :order => 'comments.id'
has_many :jobs, :through => :references
has_many :jobs_with_dependent_destroy, :source => :job, :through => :references, :dependent => :destroy

7 comments on commit c99d507

@jonleighton
Ruby on Rails member

@tenderlove @josevalim @NZKoz what do you think about putting this in 3-2-stable? (assuming we will do another RC)

@josevalim
Ruby on Rails member

Let's leave it to 4.0 since it deprecates a major API, no?

@josevalim
Ruby on Rails member

Btw, what is the reasoning here?

@josevalim
Ruby on Rails member

Nevermind, I just read #950. Seems fine for 3-2 stable if grandpa @NZKoz agrees.

@fxn
Ruby on Rails member

Not too keen on the name. includes is an eager loader, but eager_load takes the full concept for him in its name. I think I'd prefer two names at the same "level" and more explicit about their difference, like includes_join, includes_in or somesuch. With alias includes includes_in for backwards compatibility when choosing a strategy is removed.

@tenderlove
Ruby on Rails member

@jonleighton yes yes yes. Plus one million. Please put this in 3-2-stable, we need to deal with #950 before Rails 4.0.

@fxn
Ruby on Rails member

A followup for the archives.

We've explored a few options in Campfire. Since the point is that the user needs to tell AR that he needs a JOIN, one option is to stick to one method, for example includes, and add an option :join => true.

Post.includes(:comments, :join => true).where("comments.body ...")

In that approach :join would be false by default. But it has a problem we have not been able to solve satisfactorily, which is how to translate that into the options hash of association macros with a usage that does not resemble a frankestein.

The other option is to define a new method references:

Post.includes(:comments).where("comments.body ...").references(:comments)

That has several pros: It works well with macros, it allows AR to add :comments as a referenced table automatically in

where(:comments => {:body ...})

It allows AR to use JOIN for the referenced tables and IN for the rest.

There has been some more ideas but those ones have been the best ones we think, and the last one was the preferred one.

Jon is out of time to implement it for 3.2 though.

Please sign in to comment.