Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactor pluck with multiple columns

Ensure it works with mix of symbols and strings, and with a select
clause possibly containing more than one column.

Also remove support for pluck with an array of columns, in favor of
passing the list of attributes:

    Model.pluck(:a, :b)

See comments: #6500 (comment)
  • Loading branch information...
commit 6aae17e85613fe8c2816ba278f9348f168692479 1 parent 2e379c1
@carlosantoniodasilva carlosantoniodasilva authored
View
39 activerecord/lib/active_record/relation/calculations.rb
@@ -107,7 +107,6 @@ def calculate(operation, column_name, options = {})
relation = with_default_scope
if relation.equal?(self)
-
if has_include?(column_name)
construct_relation_for_association_calculations.calculate(operation, column_name, options)
else
@@ -139,9 +138,6 @@ def calculate(operation, column_name, options = {})
# # SELECT people.id FROM people
# # => [1, 2, 3]
#
- # Person.pluck([:id, :name])
- # # SELECT people.id, people.name FROM people
- #
# Person.pluck(:id, :name)
# # SELECT people.id, people.name FROM people
#
@@ -158,23 +154,19 @@ def calculate(operation, column_name, options = {})
# # => ['0', '27761', '173']
#
def pluck(*column_names)
- column_names = column_names.flatten
-
- if column_names.first.is_a?(Symbol) && self.column_names.include?(column_names.first.to_s)
- if column_names.one?
- column_names = "#{table_name}.#{column_names.first}"
+ column_names.map! do |column_name|
+ if column_name.is_a?(Symbol) && self.column_names.include?(column_name.to_s)
+ "#{table_name}.#{column_name}"
else
- column_names = column_names.collect{|column_name| "#{table_name}.#{column_name}"}
+ column_name
end
end
- if has_include?(column_names)
- construct_relation_for_association_calculations.pluck(column_names)
+ if has_include?(column_names.first)
+ construct_relation_for_association_calculations.pluck(*column_names)
else
- result = klass.connection.select_all(select(column_names).arel, nil, bind_values)
-
- keys = column_names.is_a?(Array) && !column_names.one? ? result.columns : [result.columns.first]
- columns = keys.map do |key|
+ result = klass.connection.select_all(select(column_names).arel, nil, bind_values)
+ columns = result.columns.map do |key|
klass.column_types.fetch(key) {
result.column_types.fetch(key) {
Class.new { def type_cast(v); v; end }.new
@@ -182,19 +174,14 @@ def pluck(*column_names)
}
end
- result.map do |attributes|
- if attributes.one?
- value = klass.initialize_attributes(attributes).values.first
-
- columns.first.type_cast(value)
- else
- values = klass.initialize_attributes(attributes).values
+ result = result.map do |attributes|
+ values = klass.initialize_attributes(attributes).values
- values.each_with_index.map do |value, i|
- columns[i].type_cast(value)
- end
+ columns.zip(values).map do |column, value|
+ column.type_cast(value)
end
end
+ columns.one? ? result.map!(&:first) : result
end
end
View
26 activerecord/test/cases/calculations_test.rb
@@ -532,10 +532,6 @@ def test_pluck_with_selection_clause
assert_equal [50 + 53 + 55 + 60], Account.pluck('SUM(DISTINCT(credit_limit)) as credit_limit')
end
- def test_pluck_expects_a_multiple_selection_as_array
- assert_raise(ArgumentError) { Account.pluck 'id, credit_limit' }
- end
-
def test_plucks_with_ids
assert_equal Company.all.map(&:id).sort, Company.ids.sort
end
@@ -551,14 +547,24 @@ def test_pluck_multiple_columns
assert_equal [
[1, "The First Topic"], [2, "The Second Topic of the day"],
[3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"]
- ], Topic.order(:id).pluck([:id, :title])
+ ], Topic.order(:id).pluck(:id, :title)
assert_equal [
[1, "The First Topic", "David"], [2, "The Second Topic of the day", "Mary"],
[3, "The Third Topic of the day", "Carl"], [4, "The Fourth Topic of the day", "Carl"]
- ], Topic.order(:id).pluck([:id, :title, :author_name])
- assert_equal [
- [1, "The First Topic"], [2, "The Second Topic of the day"],
- [3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"]
- ], Topic.order(:id).pluck(:id, :title)
+ ], Topic.order(:id).pluck(:id, :title, :author_name)
+ end
+
+ def test_pluck_with_multiple_columns_and_selection_clause
+ assert_equal [[1, 50], [2, 50], [3, 50], [4, 60], [5, 55], [6, 53]],
+ Account.pluck('id, credit_limit')
+ end
+
+ def test_pluck_with_multiple_columns_and_includes
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
+ companies_and_developers = Company.order('companies.id').includes(:contracts).pluck(:name, :developer_id)
+
+ assert_equal Company.count, companies_and_developers.length
+ assert_equal ["37signals", nil], companies_and_developers.first
+ assert_equal ["test", 7], companies_and_developers.last
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.