views:

111

answers:

1

Hi All,

Is there a good way to retrieve all of a specific attribute from a relationship/collection? For instance, I want a list of all the names of a person's cars. Obviously I can't do the following:

Person.Cars.Name(s)

...but does something of that nature exist in ruby (or is there an ActiveRecord helper method) that handles that? Obviously I could iterate over all the cars and append to an array, but I'd like something a bit cleaner. Any ideas?

Best.

+2  A: 

If cars is an association of a person, and name a property of a car, then you can do the following:

# person = Person.find(conditions)
person.cars.collect { |car| car.name }

Or even (thanks to ActiveSupport and/or Ruby 1.9):

person.cars.collect(&:name)

Update: this is documented in the following places:

Update 2: an example that applies formatting:

person.cars.collect { |car| "(#{car.name})" }
molf
Excellent! Thank you. Where exactly is that documented? I must admit, I have quite a time with Ruby/Rails when it comes to intuiting where to find certain functionality. Even using online documentation I'm not really able to find some of the cooler items of this nature.
humble_coder
Chuck
The reason you don't see this in the Rails docs is that Enumerable#collect (or its synonym #map) are just part of plain old Ruby.
Mike Woodhouse
Is there any way to manipulate the returned data? For instance, I want to place brackets around each returned word for formatting purposes. How would I go about doing that?
humble_coder
@humble_coder, updated with an example.
molf
humble_coder
@humble_coder, sure, you can just append .join(", ") to join the array into a single string. Even the formatted array with parenthesis. But this is starting to sound scary. You probably do not have to build a DB query yourself if you use ActiveRecord. It created specifically to handle this abstraction for you. Perhaps post a separate question to get some info how to deal with it in your specific case?
molf
Actually, the situation is a bit convoluted. I'm using Gruff to plot points for a table of various Points. The whole Person/Car thing was completely contrived. Basically I have several METERS that have associated POINTS and VALUES and I'm charting them. So for each point associated with a meter, I need to grab those values from the "values" table and plot them for that day. That being the case, I need to loop through and dynamically acquire each point/value combo for any meter at any given time. Does that make any sense?
humble_coder
@humble_coder, sort of. Does the example that adds parentheses, together with a trailing join() help you out?.
molf
Yes, it absolutely helps. I ended up using this code: ...points = self.points.collect{|p| "\'#{p.name}\'"}.join(",")...That gave me a series of single-quoted strings for placing in the query. I'm looking to do a single query, hence the join. What I need now, however, is to loop through all groups of points in the resulting query independently. Are there any cool "collect" tricks (or otherwise) for acquiring values of a specific type in an existing result set?
humble_coder
@humble_coder, you may want to look at Array#select: http://www.ruby-doc.org/core/classes/Array.html#M002191 ?
molf