Skip to content

Commit 089c7ef

Browse files
joshuay03byroot
authored andcommitted
Allow ActiveRecord::QueryMethods#pluck to accept hash args with symbol & string values
1 parent e9d01ab commit 089c7ef

File tree

4 files changed

+40
-3
lines changed

4 files changed

+40
-3
lines changed

activerecord/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
* Allow `ActiveRecord::Base#pluck` to accept hash arguments with symbol and string values.
2+
3+
```ruby
4+
Post.joins(:comments).pluck(:id, comments: :id)
5+
Post.joins(:comments).pluck("id", "comments" => "id")
6+
```
7+
8+
*Joshua Young*
9+
110
* Make Float distinguish between `float4` and `float8` in PostgreSQL.
211

312
Fixes #52742

activerecord/lib/active_record/relation/calculations.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,14 @@ 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])
278+
# Comment.joins(:person).pluck(:id, person: :id)
279279
# # SELECT comments.id, people.id FROM comments INNER JOIN people on comments.person_id = people.id
280280
# # => [[1, 2], [2, 2]]
281281
#
282+
# Comment.joins(:person).pluck(:id, person: [:id, :name])
283+
# # SELECT comments.id, people.id, people.name FROM comments INNER JOIN people on comments.person_id = people.id
284+
# # => [[1, 2, 'David'], [2, 2, 'David']]
285+
#
282286
# Person.pluck(Arel.sql('DATEDIFF(updated_at, created_at)'))
283287
# # SELECT DATEDIFF(updated_at, created_at) FROM people
284288
# # => ['0', '27761', '173']

activerecord/lib/active_record/relation/query_methods.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,25 @@ def arel_columns(columns)
19561956
end
19571957
end
19581958

1959+
def arel_columns_from_array(columns, table_name = model.table_name)
1960+
columns.map do |column|
1961+
arel_column("#{table_name}.#{column}")
1962+
end
1963+
end
1964+
1965+
def arel_columns_from_hash(fields)
1966+
fields.flat_map do |table_name, columns|
1967+
case columns
1968+
when Array
1969+
arel_columns_from_array(columns, table_name)
1970+
when Symbol, String
1971+
arel_column(columns)
1972+
else
1973+
raise TypeError, "Expected Symbol, String or Array, got: #{columns.class}"
1974+
end
1975+
end
1976+
end
1977+
19591978
def arel_column(field)
19601979
field = field.name if is_symbol = field.is_a?(Symbol)
19611980

@@ -2194,14 +2213,14 @@ def check_if_method_has_arguments!(method_name, args, message = nil)
21942213
def process_select_args(fields)
21952214
fields.flat_map do |field|
21962215
if field.is_a?(Hash)
2197-
arel_columns_from_hash(field)
2216+
arel_column_aliases_from_hash(field)
21982217
else
21992218
field
22002219
end
22012220
end
22022221
end
22032222

2204-
def arel_columns_from_hash(fields)
2223+
def arel_column_aliases_from_hash(fields)
22052224
fields.flat_map do |key, columns_aliases|
22062225
case columns_aliases
22072226
when Hash

activerecord/test/cases/calculations_test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,10 @@ def test_pluck_with_hash_argument
976976
[2, "The Second Topic of the day"],
977977
[3, "The Third Topic of the day"]
978978
]
979+
assert_equal expected, Topic.order(:id).limit(3).pluck(:id, topics: :title)
980+
assert_equal expected, Topic.order(:id).limit(3).pluck("id", "topics" => "title")
979981
assert_equal expected, Topic.order(:id).limit(3).pluck(:id, topics: [:title])
982+
assert_equal expected, Topic.order(:id).limit(3).pluck("id", "topics" => ["title"])
980983
end
981984

982985
def test_pluck_with_hash_argument_with_multiple_tables
@@ -985,6 +988,8 @@ def test_pluck_with_hash_argument_with_multiple_tables
985988
[1, 2, "Thank you again for the welcome"],
986989
[2, 3, "Don't think too hard"]
987990
]
991+
assert_equal expected, Post.joins(:comments).order(posts: { id: :asc }, comments: { id: :asc }).limit(3).pluck(:id, comments: [:id, :body])
992+
assert_equal expected, Post.joins(:comments).order(posts: { id: :asc }, comments: { id: :asc }).limit(3).pluck(posts: :id, comments: [:id, :body])
988993
assert_equal expected, Post.joins(:comments).order(posts: { id: :asc }, comments: { id: :asc }).limit(3).pluck(posts: [:id], comments: [:id, :body])
989994
end
990995

0 commit comments

Comments
 (0)