Skip to content

Commit 82c02ef

Browse files
committed
Allow ActiveRecord::Base#pluck to accept hash values
1 parent 92591eb commit 82c02ef

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

activerecord/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
* Allow `ActiveRecord::Base#pluck` to accept hash values
2+
3+
```ruby
4+
# Before
5+
Post.joins(:comments).pluck("posts.id", "comments.id", "comments.body")
6+
7+
# After
8+
Post.joins(:comments).pluck(posts: [:id], comments: [:id, :body])
9+
```
10+
11+
*fatkodima*
12+
113
* Raise an `ActiveRecord::ActiveRecordError` error when the MySQL database returns an invalid version string.
214

315
*Kevin McPhillips*

activerecord/lib/active_record/relation/calculations.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ def calculate(operation, column_name)
275275
# # SELECT people.id FROM people WHERE people.age = 21 LIMIT 5
276276
# # => [2, 3]
277277
#
278+
# Comment.joins(:person).pluck(:id, person: [:id])
279+
# # SELECT comments.id, people.id FROM comments INNER JOIN people on comments.person_id = people.id
280+
# # => [[1, 2], [2, 2]]
281+
#
278282
# Person.pluck(Arel.sql('DATEDIFF(updated_at, created_at)'))
279283
# # SELECT DATEDIFF(updated_at, created_at) FROM people
280284
# # => ['0', '27761', '173']
@@ -302,7 +306,7 @@ def pluck(*column_names)
302306
relation = apply_join_dependency
303307
relation.pluck(*column_names)
304308
else
305-
klass.disallow_raw_sql!(column_names.flatten)
309+
klass.disallow_raw_sql!(flattened_args(column_names))
306310
columns = arel_columns(column_names)
307311
relation = spawn
308312
relation.select_values = columns

activerecord/lib/active_record/relation/query_methods.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,6 +1854,8 @@ def arel_columns(columns)
18541854
arel_column(field, &:itself)
18551855
when Proc
18561856
field.call
1857+
when Hash
1858+
arel_columns_from_hash(field)
18571859
else
18581860
field
18591861
end
@@ -1944,8 +1946,8 @@ def validate_order_args(args)
19441946
end
19451947
end
19461948

1947-
def flattened_args(order_args)
1948-
order_args.flat_map { |e| (e.is_a?(Hash) || e.is_a?(Array)) ? flattened_args(e.to_a) : e }
1949+
def flattened_args(args)
1950+
args.flat_map { |e| (e.is_a?(Hash) || e.is_a?(Array)) ? flattened_args(e.to_a) : e }
19491951
end
19501952

19511953
def preprocess_order_args(order_args)
@@ -2081,14 +2083,14 @@ def check_if_method_has_arguments!(method_name, args, message = nil)
20812083
def process_select_args(fields)
20822084
fields.flat_map do |field|
20832085
if field.is_a?(Hash)
2084-
transform_select_hash_values(field)
2086+
arel_columns_from_hash(field)
20852087
else
20862088
field
20872089
end
20882090
end
20892091
end
20902092

2091-
def transform_select_hash_values(fields)
2093+
def arel_columns_from_hash(fields)
20922094
fields.flat_map do |key, columns_aliases|
20932095
case columns_aliases
20942096
when Hash

activerecord/test/cases/calculations_test.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,30 @@ def test_pluck_with_selection_clause
952952
assert_equal [50 + 53 + 55 + 60], Account.pluck(Arel.sql("SUM(DISTINCT(credit_limit))"))
953953
end
954954

955+
def test_pluck_with_hash_argument
956+
expected = [
957+
[1, "The First Topic"],
958+
[2, "The Second Topic of the day"],
959+
[3, "The Third Topic of the day"]
960+
]
961+
assert_equal expected, Topic.order(:id).limit(3).pluck(:id, topics: [:title])
962+
end
963+
964+
def test_pluck_with_hash_argument_with_multiple_tables
965+
expected = [
966+
[1, 1, "Thank you for the welcome"],
967+
[1, 2, "Thank you again for the welcome"],
968+
[2, 3, "Don't think too hard"]
969+
]
970+
assert_equal expected, Post.joins(:comments).order(posts: { id: :asc }, comments: { id: :asc }).limit(3).pluck(posts: [:id], comments: [:id, :body])
971+
end
972+
973+
def test_pluck_with_hash_argument_containing_non_existent_field
974+
assert_raises(ActiveRecord::StatementInvalid) do
975+
Topic.pluck(topics: [:non_existent])
976+
end
977+
end
978+
955979
def test_ids
956980
assert_equal Company.all.map(&:id).sort, Company.all.ids.sort
957981
end

0 commit comments

Comments
 (0)