diff options
-rw-r--r-- | activerecord/CHANGELOG.md | 9 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/collection_proxy.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/base.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/calculations.rb | 17 | ||||
-rw-r--r-- | activerecord/test/cases/calculations_test.rb | 25 | ||||
-rw-r--r-- | railties/guides/source/active_record_querying.textile | 9 |
6 files changed, 62 insertions, 2 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 1a95b8e95e..f798b03ea1 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,14 @@ ## Rails 3.2.0 (unreleased) ## + +* Implemented ActiveRecord::Relation#pluck method + + Method returns Array of column value from table under ActiveRecord model + + Client.pluck(:id) + + *Bogdan Gusiev* + * Automatic closure of connections in threads is deprecated. For example the following code is deprecated: diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 3181ca9a32..80bc4990d2 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -39,7 +39,7 @@ module ActiveRecord instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to|proxy_/ } delegate :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, - :lock, :readonly, :having, :to => :scoped + :lock, :readonly, :having, :pluck, :to => :scoped delegate :target, :load_target, :loaded?, :scoped, :to => :@association diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 484fe5fb16..2a02380591 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -449,7 +449,7 @@ module ActiveRecord #:nodoc: delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :uniq, :to => :scoped - delegate :count, :average, :minimum, :maximum, :sum, :calculate, :to => :scoped + delegate :count, :average, :minimum, :maximum, :sum, :calculate, :pluck, :to => :scoped def inherited(child_class) #:nodoc: # force attribute methods to be higher in inheritance hierarchy than other generated methods diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index af86771d2d..0f57e9831d 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -166,6 +166,23 @@ module ActiveRecord 0 end + # This method is designed to perform select by a single column as direct SQL query + # Returns <tt>Array</tt> with values of the specified column name + # The values has same data type as column. + # + # Examples: + # + # Person.pluck(:id) # SELECT people.id FROM people + # Person.uniq.pluck(:role) # SELECT DISTINCT role FROM people + # Person.where(:confirmed => true).limit(5).pluck(:id) + # + def pluck(column_name) + scope = self.select(column_name) + self.connection.select_values(scope.to_sql).map! do |value| + type_cast_using_column(value, column_for(column_name)) + end + end + private def perform_calculation(operation, column_name, options = {}) diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index c38814713a..5abf3d1af4 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -1,5 +1,6 @@ require "cases/helper" require 'models/company' +require "models/contract" require 'models/topic' require 'models/edge' require 'models/club' @@ -446,4 +447,28 @@ class CalculationsTest < ActiveRecord::TestCase distinct_authors_for_approved_count = Topic.group(:approved).count(:author_name, :distinct => true)[true] assert_equal distinct_authors_for_approved_count, 2 end + + def test_pluck + assert_equal [1,2,3,4], Topic.order(:id).pluck(:id) + end + + def test_pluck_type_cast + topic = topics(:first) + relation = Topic.where(:id => topic.id) + assert_equal [ topic.approved ], relation.pluck(:approved) + assert_equal [ topic.last_read ], relation.pluck(:last_read) + assert_equal [ topic.written_on ], relation.pluck(:written_on) + + end + + def test_pluck_and_uniq + assert_equal [50, 53, 55, 60], Account.order(:credit_limit).uniq.pluck(:credit_limit) + end + + def test_pluck_in_relation + company = Company.first + contract = company.contracts.create! + assert_equal [contract.id], company.contracts.pluck(:id) + end + end diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index c4724f182e..073f7c143d 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -1146,6 +1146,15 @@ h3. +select_all+ Client.connection.select_all("SELECT * FROM clients WHERE id = '1'") </ruby> +h3. +pluck+ + +<tt>pluck</tt> can be used to query single column from table under model. It accepts column name as argument and returns Array of values of the specified column with corresponding data type. + +<ruby> +Client.where(:active => true).pluck(:id) # SELECT id FROM clients WHERE clients.active +Client.uniq.pluck(:role) # SELECT DISTINCT role FROM clients +</ruby> + h3. Existence of Objects If you simply want to check for the existence of the object there's a method called +exists?+. This method will query the database using the same query as +find+, but instead of returning an object or collection of objects it will return either +true+ or +false+. |