Skip to content

Commit

Permalink
Merge pull request #1915 from bogdan/active_record_map
Browse files Browse the repository at this point in the history
ActiveRecord::Base.map method for direct select by single column
  • Loading branch information
jonleighton committed Nov 30, 2011
2 parents 38ab982 + a382d60 commit 271308c
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 2 deletions.
9 changes: 9 additions & 0 deletions activerecord/CHANGELOG.md
@@ -1,5 +1,14 @@
## Rails 3.2.0 (unreleased) ## ## 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 * Automatic closure of connections in threads is deprecated. For example
the following code is deprecated: the following code is deprecated:


Expand Down
Expand Up @@ -39,7 +39,7 @@ class CollectionProxy # :nodoc:
instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to|proxy_/ } 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, 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, delegate :target, :load_target, :loaded?, :scoped,
:to => :@association :to => :@association
Expand Down
2 changes: 1 addition & 1 deletion activerecord/lib/active_record/base.rb
Expand Up @@ -449,7 +449,7 @@ class << self # Class methods
delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins,
:where, :preload, :eager_load, :includes, :from, :lock, :readonly, :where, :preload, :eager_load, :includes, :from, :lock, :readonly,
:having, :create_with, :uniq, :to => :scoped :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: def inherited(child_class) #:nodoc:
# force attribute methods to be higher in inheritance hierarchy than other generated methods # force attribute methods to be higher in inheritance hierarchy than other generated methods
Expand Down
17 changes: 17 additions & 0 deletions activerecord/lib/active_record/relation/calculations.rb
Expand Up @@ -166,6 +166,23 @@ def calculate(operation, column_name, options = {})
0 0
end 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 private


def perform_calculation(operation, column_name, options = {}) def perform_calculation(operation, column_name, options = {})
Expand Down
25 changes: 25 additions & 0 deletions activerecord/test/cases/calculations_test.rb
@@ -1,5 +1,6 @@
require "cases/helper" require "cases/helper"
require 'models/company' require 'models/company'
require "models/contract"
require 'models/topic' require 'models/topic'
require 'models/edge' require 'models/edge'
require 'models/club' require 'models/club'
Expand Down Expand Up @@ -446,4 +447,28 @@ def test_distinct_is_honored_when_used_with_count_operation_after_group
distinct_authors_for_approved_count = Topic.group(:approved).count(:author_name, :distinct => true)[true] distinct_authors_for_approved_count = Topic.group(:approved).count(:author_name, :distinct => true)[true]
assert_equal distinct_authors_for_approved_count, 2 assert_equal distinct_authors_for_approved_count, 2
end 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 end
9 changes: 9 additions & 0 deletions railties/guides/source/active_record_querying.textile
Expand Up @@ -1146,6 +1146,15 @@ h3. +select_all+
Client.connection.select_all("SELECT * FROM clients WHERE id = '1'") Client.connection.select_all("SELECT * FROM clients WHERE id = '1'")
</ruby> </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 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+. 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+.
Expand Down

0 comments on commit 271308c

Please sign in to comment.