Breno
Breno

Reputation: 6292

Fetch ActiveRecord query result as an array of hashes with chosen attributes

The model User has first, last and login as attributes. It also has a method called name that joins first and last.

What I want is to iterate through the Users records and create an array of hashes with the attributes I want. Like so:

results = []
User.all.map do |user|
    record = {}
    record["login"] = user.login
    record["name"] = user.name
    results << record
end

Is there a cleaner way in Ruby to do this?

Upvotes: 1

Views: 4591

Answers (4)

potashin
potashin

Reputation: 44581

You can use ActiveRecord::QueryMethods#select and ActiveRecord::Relation#as_json:

User.select(:login, '(first || last) as name').as_json(except: :id)

Upvotes: 3

Paul Hoffer
Paul Hoffer

Reputation: 12906

Trying to map over User.all is going to cause performance issues (later, if not now). To avoid instantiating all User objects, you can use pluck to get the data directly out of the DB and then map it.

results = User.all.pluck(:login, :first, :last).map do |login, first, last|
  { 'login' => login, 'name' => first << last }
end

Instantiating all the users is going to be problematic. Even the as_json relation method is going to do that. It may even be a problem using this method, depending on how many users there are.

Also, this assumes that User#name really just does first + last. If it's different, you can change the logic in the block.

Upvotes: 3

jrochkind
jrochkind

Reputation: 23317

The poorly named and poorly documented method ActiveRecord::Result#to_hash does what you want, I think.

User.select(:login, :name).to_hash

Poorly named because it does in fact return an array of Hash, which seems pretty poor form for a method named to_hash.

Upvotes: 0

spickermann
spickermann

Reputation: 106802

I would write:

results = User.all.map { |u| { login: u.login, name: u.name } }

Upvotes: 1

Related Questions