Skip to content

Commit c210600

Browse files
committed
Ensure none constraint scopes don’t trigger a query
rails#47800 refactored how `Relation#none` worked, and one side effect of this change was that if you had an association like this: `has_many :comments_none, ->(post) { none }, class_name: "Comment”` reading the association caused a query to happen, despite the `none` in the passed in scope. As it turns out, this is because the association performs a merge of the two scopes, and the `@none` instance variable wasn’t getting copied over to the merged scope, so the upfront guard clause checking `@none` in `#exec_main_query`. Updating the `Merger` object to add a check for null relations and call `none!` ensures the query doesn’t run in this particular scenario.
1 parent 2675c90 commit c210600

File tree

2 files changed

+12
-0
lines changed

2 files changed

+12
-0
lines changed

activerecord/lib/active_record/relation/merger.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ def merge
6969
end
7070
end
7171

72+
relation.none! if other.null_relation?
73+
7274
merge_select_values
7375
merge_multi_values
7476
merge_single_values

activerecord/test/cases/null_relation_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ def test_null_relation_content_size_methods
5959
end
6060
end
6161

62+
def test_null_relation_used_with_constraints
63+
post = Post.first
64+
assert_no_queries do
65+
scope = post.comments
66+
none = Post.none
67+
scope = scope.merge(none)
68+
assert_equal 0, scope.size
69+
end
70+
end
71+
6272
def test_null_relation_metadata_methods
6373
assert_includes Developer.none.to_sql, " WHERE (1=0)"
6474
assert_equal({}, Developer.none.where_values_hash)

0 commit comments

Comments
 (0)