Reputation: 3633
I have this query:
Client.select("name as dname")
Which is working fine.
Client.select("name as dname").first.dname
=> "Google"
Now I want to get all dnames as an array but pluck method does not work as dname is not column name.
2.2.5 :040 > Client.select("name as dname").pluck(:dname)
(0.6ms) SELECT dname FROM "clients"
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "dname" does not exist
How to get array of dnames? Is there any method like pluck which works on column name alias which is defined using as.
I can do this
Client.select("name as dname").map{|d| d.dname}
But looping through every record is not making any sense to me
Upvotes: 14
Views: 11291
Reputation: 1972
If you are computing a virtual column or aliased column you should use this form with Arel.sql otherwise column should exists in the table. For example for concating two columns into one virtual one:
Client.pluck(Arel.sql("one_column || two_column"))
and the SQL:
SELECT one_column || two_column FROM "clients"
Upvotes: 1
Reputation: 3633
Well my understanding of pluck was wrong. from apidock I understood that
Use pluck as a shortcut to select one or more attributes without loading a bunch of records just to grab the attributes you want.
So,
Client.select("name as dname").pluck(:dname)
Should be written like this
Client.pluck(:name)
Upvotes: 15
Reputation: 3908
select
and pluck
don't play well together, but I've use a workaround that joins the aliased column onto the query object, allowing pluck. I usually write joins like this as scopes starting with with_
class Client
scope :with_dname , -> {
# Build a subquery SQL snippet
# Since we will be joining it onto the base table, we need to select the id column as well
subquery = select("name AS dname, #{table_name}.id").to_sql
# join the subquery to base model
joins("JOIN (#{subquery}) as addendum ON addendum.id = #{table_name}.id")
}
end
# this will work
Client.with_dname.first.pluck(:dname) #=> ["Google"]
# this may be more efficient
Client.limit(1).with_dname.first.pluck(:dname) #=> ["Google"]
Upvotes: 2
Reputation: 1613
Use this code:
Client.select("name as dname").map{|d| d.dname}
Upvotes: 1