What is &:id
in Role.all.map(&:id)
. If (&:id)
is shorthand for {|a| a.id}
, then how to perform some method over any field individually. For example: Role.all.map(&:id.to_s)
. It is giving error:
wrong argument type String (expected Proc)
What is &:id
in Role.all.map(&:id)
. If (&:id)
is shorthand for {|a| a.id}
, then how to perform some method over any field individually. For example: Role.all.map(&:id.to_s)
. It is giving error:
wrong argument type String (expected Proc)
So &:something
is a shortcut to a process. It's the same as a code block being defined after a do
, only it can only call a single method on each item in the array.
These three code examples will do effectively the same thing*...
Role.all.map do |role|
role.id
end
In this one, the do
and end
are replaced with curly braces...
Role.all.map{|r| r.id}
And as we're only calling one method in that block, we can replace it with the shortened syntax you're asking about:
Role.all.map(&:id)
Aside to your question, there is an optimation by which you can get all the ids from Role.
The above block will recall all the rows from your ROLES
table, initialize a Role
object, then get it's id
property. But ActiveRecord provides a method which will just retrieve the id
property for every row in the table, and not bother creating a full-fat Role
object for each one.
Role.pluck(:id)
This also works for a query on Role...
Role.where("name like '%user'").pluck(:id)
If all you want from the Roles is an id, this is a much more efficient way to get it.
* Sergio disagrees that they are identical because of some subtle differences in run order... You probably don't need to worry about this.