Skip to content
This repository

Relation subqueries #188

Closed
wants to merge 1 commit into from

2 participants

pfenig Aaron Patterson
pfenig

ActiveRecord::Relation where clauses hash syntax accepts an ActiveRecord::Relation as a value, but it maps the relation to ids when it could just use a subquery. By converting the Relation to an ast we can now accept any subquery.

Model.where(:id => AnotherModel.some_scope.select(:some_id))

will only run one query and it supports references to tables from the outer query.

Have corresponded with @tenderlove on this.

pfenig removed an unnecessary second query when passing an ActiveRecord::Rel…
…ation to a where clause. And added ability to use subselects in where clauses.
0816468
Aaron Patterson
Owner

Merged to master and pushed. Thanks.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Feb 11, 2011
pfenig removed an unnecessary second query when passing an ActiveRecord::Rel…
…ation to a where clause. And added ability to use subselects in where clauses.
0816468
This page is out of date. Refresh to see the latest.
5  activerecord/lib/active_record/relation/predicate_builder.rb
@@ -18,7 +18,10 @@ def self.build_from_hash(engine, attributes, default_table)
18 18
           attribute = table[column.to_sym]
19 19
 
20 20
           case value
21  
-          when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::Relation
  21
+          when ActiveRecord::Relation
  22
+            value.select_values = Array.wrap("#{value.klass.quoted_table_name}.id") if value.select_values.empty?
  23
+            attribute.in(value.arel.ast)
  24
+          when Array, ActiveRecord::Associations::AssociationCollection
22 25
             values = value.to_a.map { |x|
23 26
               x.is_a?(ActiveRecord::Base) ? x.id : x
24 27
             }
29  activerecord/test/cases/relations_test.rb
@@ -467,7 +467,7 @@ def test_find_by_id_with_list_of_ar
467 467
     authors = Author.find_by_id([author])
468 468
     assert_equal author, authors
469 469
   end
470  
-
  470
+  
471 471
   def test_find_all_using_where_twice_should_or_the_relation
472 472
     david = authors(:david)
473 473
     relation = Author.unscoped
@@ -488,6 +488,33 @@ def test_find_all_with_multiple_ors
488 488
     end
489 489
     assert_equal [david], relation.all
490 490
   end
  491
+  
  492
+  def test_find_all_using_where_with_relation
  493
+    david = authors(:david)
  494
+    # switching the lines below would succeed in current rails
  495
+    # assert_queries(2) {
  496
+    assert_queries(1) {
  497
+      relation = Author.where(:id => Author.where(:id => david.id))
  498
+      assert_equal [david], relation.all
  499
+    }
  500
+  end
  501
+
  502
+  def test_find_all_using_where_with_relation_with_joins
  503
+    david = authors(:david)
  504
+    assert_queries(1) {
  505
+      relation = Author.where(:id => Author.joins(:posts).where(:id => david.id))
  506
+      assert_equal [david], relation.all
  507
+    }
  508
+  end
  509
+
  510
+  
  511
+  def test_find_all_using_where_with_relation_with_select_to_build_subquery
  512
+    david = authors(:david)
  513
+    assert_queries(1) {
  514
+      relation = Author.where(:name => Author.where(:id => david.id).select(:name))
  515
+      assert_equal [david], relation.all
  516
+    }
  517
+  end
491 518
 
492 519
   def test_exists
493 520
     davids = Author.where(:name => 'David')
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.