Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

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 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
Commits on Feb 11, 2011
  1. pfenig

    removed an unnecessary second query when passing an ActiveRecord::Rel…

    pfenig authored
    …ation to a where clause. And added ability to use subselects in where clauses.
This page is out of date. Refresh to see the latest.
5 activerecord/lib/active_record/relation/predicate_builder.rb
View
@@ -18,7 +18,10 @@ def self.build_from_hash(engine, attributes, default_table)
attribute = table[column.to_sym]
case value
- when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::Relation
+ when ActiveRecord::Relation
+ value.select_values = Array.wrap("#{value.klass.quoted_table_name}.id") if value.select_values.empty?
+ attribute.in(value.arel.ast)
+ when Array, ActiveRecord::Associations::AssociationCollection
values = value.to_a.map { |x|
x.is_a?(ActiveRecord::Base) ? x.id : x
}
29 activerecord/test/cases/relations_test.rb
View
@@ -467,7 +467,7 @@ def test_find_by_id_with_list_of_ar
authors = Author.find_by_id([author])
assert_equal author, authors
end
-
+
def test_find_all_using_where_twice_should_or_the_relation
david = authors(:david)
relation = Author.unscoped
@@ -488,6 +488,33 @@ def test_find_all_with_multiple_ors
end
assert_equal [david], relation.all
end
+
+ def test_find_all_using_where_with_relation
+ david = authors(:david)
+ # switching the lines below would succeed in current rails
+ # assert_queries(2) {
+ assert_queries(1) {
+ relation = Author.where(:id => Author.where(:id => david.id))
+ assert_equal [david], relation.all
+ }
+ end
+
+ def test_find_all_using_where_with_relation_with_joins
+ david = authors(:david)
+ assert_queries(1) {
+ relation = Author.where(:id => Author.joins(:posts).where(:id => david.id))
+ assert_equal [david], relation.all
+ }
+ end
+
+
+ def test_find_all_using_where_with_relation_with_select_to_build_subquery
+ david = authors(:david)
+ assert_queries(1) {
+ relation = Author.where(:name => Author.where(:id => david.id).select(:name))
+ assert_equal [david], relation.all
+ }
+ end
def test_exists
davids = Author.where(:name => 'David')
Something went wrong with that request. Please try again.