aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBogdan Gusiev <agresso@gmail.com>2011-11-30 11:03:00 +0200
committerBogdan Gusiev <agresso@gmail.com>2011-11-30 11:03:00 +0200
commita382d60f6abc94b6a965525872f858e48abc00de (patch)
tree969d8b7d6321f7868e2f613f6f44987f3f471911
parentd9c288207731e61c40ce6276fd91f0b800d3fabb (diff)
downloadrails-a382d60f6abc94b6a965525872f858e48abc00de.tar.gz
rails-a382d60f6abc94b6a965525872f858e48abc00de.tar.bz2
rails-a382d60f6abc94b6a965525872f858e48abc00de.zip
ActiveRecord::Relation#pluck method
-rw-r--r--activerecord/CHANGELOG.md9
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb2
-rw-r--r--activerecord/lib/active_record/base.rb2
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb17
-rw-r--r--activerecord/test/cases/calculations_test.rb25
-rw-r--r--railties/guides/source/active_record_querying.textile9
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+.