Skip to content

Commit

Permalink
Merge pull request #32617 from tgturner/size-should-use-available-ass…
Browse files Browse the repository at this point in the history
…ociation

Loaded associations should not run a new query when size is called
  • Loading branch information
kamipo committed Apr 27, 2018
2 parents 46b46e8 + b07b970 commit 0a8fe15
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
5 changes: 5 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
* Ensure `Associations::CollectionAssociation#size` and `Associations::CollectionAssociation#empty?`
use loaded association ids if present.

*Graham Turner*

* Add support to preload associations of polymorphic associations when not all the records have the requested associations.

*Dana Sherson*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ def destroy(*records)
def size
if !find_target? || loaded?
target.size
elsif @association_ids && target.empty?
@association_ids.size
elsif !association_scope.group_values.empty?
load_target.size
elsif !association_scope.distinct_value && !target.empty?
Expand All @@ -231,7 +233,7 @@ def size
# loaded and you are going to fetch the records anyway it is better to
# check <tt>collection.length.zero?</tt>.
def empty?
if loaded?
if loaded? || @association_ids
size.zero?
else
target.empty? && !scope.exists?
Expand Down
74 changes: 74 additions & 0 deletions activerecord/test/cases/associations/has_many_associations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,16 @@ def test_collection_size_with_dirty_target
assert_equal 1, post.readers.size
end

def test_collection_empty_with_dirty_target
post = posts(:thinking)
assert_equal [], post.reader_ids
assert_empty post.readers
post.readers.reset
post.readers.build
assert_equal [], post.reader_ids
assert_not_empty post.readers
end

def test_collection_size_twice_for_regressions
post = posts(:thinking)
assert_equal 0, post.readers.size
Expand Down Expand Up @@ -2573,6 +2583,70 @@ def self.name
end
end

test "calling size on an association that has not been loaded performs a query" do
car = Car.create!
Bulb.create(car_id: car.id)

car_two = Car.create!

assert_queries(1) do
assert_equal 1, car.bulbs.size
end

assert_queries(1) do
assert_equal 0, car_two.bulbs.size
end
end

test "calling size on an association that has been loaded does not perform query" do
car = Car.create!
Bulb.create(car_id: car.id)
car.bulb_ids

car_two = Car.create!
car_two.bulb_ids

assert_no_queries do
assert_equal 1, car.bulbs.size
end

assert_no_queries do
assert_equal 0, car_two.bulbs.size
end
end

test "calling empty on an association that has not been loaded performs a query" do
car = Car.create!
Bulb.create(car_id: car.id)

car_two = Car.create!

assert_queries(1) do
assert_not_empty car.bulbs
end

assert_queries(1) do
assert_empty car_two.bulbs
end
end

test "calling empty on an association that has been loaded does not performs query" do
car = Car.create!
Bulb.create(car_id: car.id)
car.bulb_ids

car_two = Car.create!
car_two.bulb_ids

assert_no_queries do
assert_not_empty car.bulbs
end

assert_no_queries do
assert_empty car_two.bulbs
end
end

class AuthorWithErrorDestroyingAssociation < ActiveRecord::Base
self.table_name = "authors"
has_many :posts_with_error_destroying,
Expand Down

0 comments on commit 0a8fe15

Please sign in to comment.