From 80cc0d323ba08a51d4299cb4fc34f157818fead4 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 9 Feb 2018 10:30:19 -0800 Subject: Add Relation#pick as short-hand for single-value plucks (#31941) * Add Relation#pick as short-hand for single-value plucks --- .../lib/active_record/relation/calculations.rb | 18 ++++++++++++++++++ activerecord/test/cases/calculations_test.rb | 10 ++++++++++ 2 files changed, 28 insertions(+) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index dba2f33dd4..6a3bd6a1f9 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -200,6 +200,24 @@ module ActiveRecord end end + # Pick the value(s) from the named column(s) in the current relation. + # This is short-hand for `relation.limit(1).pluck(*column_names).first`, and is primarily useful + # when you have a relation that's already narrowed down to a single row. + # + # Just like #pluck, #pick will only load the actual value, not the entire record object, so it's also + # more efficient. The value is, again like with pluck, typecast by the column type. + # + # Person.where(id: 1).pick(:name) + # # SELECT people.name FROM people WHERE id = 1 LIMIT 1 + # # => 'David' + # + # Person.where(id: 1).pick(:name, :email_address) + # # SELECT people.name, people.email_address FROM people WHERE id = 1 LIMIT 1 + # # => [ 'David', 'david@loudthinking.com' ] + def pick(*column_names) + limit(1).pluck(*column_names).first + end + # Pluck all the ID's for the relation using the table's primary key # # Person.ids # SELECT people.id FROM people diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 82b15e565b..ec8bc913a1 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -793,6 +793,16 @@ class CalculationsTest < ActiveRecord::TestCase end end + def test_pick_one + assert_equal "The First Topic", Topic.order(:id).pick(:heading) + assert_nil Topic.where("1=0").pick(:heading) + end + + def test_pick_two + assert_equal ["David", "david@loudthinking.com"], Topic.order(:id).pick(:author_name, :author_email_address) + assert_nil Topic.where("1=0").pick(:author_name, :author_email_address) + end + def test_grouped_calculation_with_polymorphic_relation part = ShipPart.create!(name: "has trinket") part.trinkets.create! -- cgit v1.2.3