From 3a8a9979acab6a6f4c6d759521c052fe2ac46d2b Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 28 Jul 2016 23:31:09 +0900 Subject: `pluck` should use `records` (`load_target`) when `loaded?` is true --- .../lib/active_record/associations/collection_proxy.rb | 13 ++++++++++++- activerecord/lib/active_record/relation/calculations.rb | 2 +- activerecord/test/cases/associations_test.rb | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 806a905323..7c96341f40 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -28,7 +28,6 @@ module ActiveRecord # is computed directly through SQL and does not trigger by itself the # instantiation of the actual post records. class CollectionProxy < Relation - delegate(*(ActiveRecord::Calculations.public_instance_methods - [:count]), to: :scope) delegate :exists?, :update_all, :arel, to: :scope def initialize(klass, association) #:nodoc: @@ -738,6 +737,14 @@ module ActiveRecord @association.count(column_name, &block) end + def calculate(operation, column_name) + null_scope? ? scope.calculate(operation, column_name) : super + end + + def pluck(*column_names) + null_scope? ? scope.pluck(*column_names) : super + end + # Returns the size of the collection. If the collection hasn't been loaded, # it executes a SELECT COUNT(*) query. Else it calls collection.size. # @@ -1073,6 +1080,10 @@ module ActiveRecord private + def null_scope? + @association.null_scope? + end + def exec_queries load_target end diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index a97b71815a..24b1131752 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -160,7 +160,7 @@ module ActiveRecord # def pluck(*column_names) if loaded? && (column_names.map(&:to_s) - @klass.attribute_names - @klass.attribute_aliases.keys).empty? - return @records.pluck(*column_names) + return records.pluck(*column_names) end if has_include?(column_names.first) diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb index 7efacb44f3..671cde3a68 100644 --- a/activerecord/test/cases/associations_test.rb +++ b/activerecord/test/cases/associations_test.rb @@ -258,6 +258,13 @@ class AssociationProxyTest < ActiveRecord::TestCase assert_no_queries { david.posts.first! } end + def test_pluck_uses_loaded_target + david = authors(:david) + assert_equal david.posts.pluck(:title), david.posts.load.pluck(:title) + assert david.posts.loaded? + assert_no_queries { david.posts.pluck(:title) } + end + def test_reset_unloads_target david = authors(:david) david.posts.reload -- cgit v1.2.3