From 3a8a9979acab6a6f4c6d759521c052fe2ac46d2b Mon Sep 17 00:00:00 2001
From: Ryuta Kamizono <kamipo@gmail.com>
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(-)

(limited to 'activerecord')

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 <tt>SELECT COUNT(*)</tt> query. Else it calls <tt>collection.size</tt>.
       #
@@ -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