diff options
| -rw-r--r-- | activerecord/lib/active_record/result.rb | 19 | ||||
| -rw-r--r-- | activerecord/test/cases/calculations_test.rb | 12 | 
2 files changed, 26 insertions, 5 deletions
diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb index 11626c8e31..ffef229be2 100644 --- a/activerecord/lib/active_record/result.rb +++ b/activerecord/lib/active_record/result.rb @@ -97,12 +97,21 @@ module ActiveRecord      end      def cast_values(type_overrides = {}) # :nodoc: -      types = columns.map { |name| column_type(name, type_overrides) } -      result = rows.map do |values| -        types.zip(values).map { |type, value| type.deserialize(value) } -      end +      if columns.one? +        # Separated to avoid allocating an array per row + +        type = column_type(columns.first, type_overrides) -      columns.one? ? result.map!(&:first) : result +        rows.map do |(value)| +          type.deserialize(value) +        end +      else +        types = columns.map { |name| column_type(name, type_overrides) } + +        rows.map do |values| +          Array.new(values.size) { |i| types[i].deserialize(values[i]) } +        end +      end      end      def initialize_copy(other) diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 6ceac59eec..5c9ed42173 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -642,6 +642,18 @@ class CalculationsTest < ActiveRecord::TestCase      assert_equal [ topic.written_on ], relation.pluck(:written_on)    end +  def test_pluck_with_type_cast_does_not_corrupt_the_query_cache +    topic = topics(:first) +    relation = Topic.where(id: topic.id) +    assert_queries 1 do +      Topic.cache do +        kind = relation.select(:written_on).load.first.read_attribute_before_type_cast(:written_on).class +        relation.pluck(:written_on) +        assert_kind_of kind, relation.select(:written_on).load.first.read_attribute_before_type_cast(:written_on) +      end +    end +  end +    def test_pluck_and_distinct      assert_equal [50, 53, 55, 60], Account.order(:credit_limit).distinct.pluck(:credit_limit)    end  | 
