views:

40

answers:

3

I am doing an ActiveRecord find on a model as such

@foo = MyModel.find(:all, :select => 'year')

As you can see, I only need the year column from this, so my ideal output would be

["2008", "2009", "2010"]

Instead, though, I get an a hash of the models, with each one containing the year, as such:

[#<MyModel year: "2008">, #<MyModel year: "2009">, #<MyModel year: "2010">]

I can loop through it as such to convert it to my ideal output:

@years = []
for bar in @foo
    @years.push(bar.year)
end

but is there a way to retrieve this result to begin with? (i.e. without going through the extra processing?). If there is not, what is a more concise way to do this processing?

Thank you.

+2  A: 

try:

@foo = MyModel.find(:all, :select => 'year').map(&:year)

You also can call .uniq() on the result to remove duplicates.

@foo = MyModel.find(:all, :select => 'year').map(&:year).uniq

This is the short form for

@foo = MyModel.find(:all, :select => 'year').map{ |model| model.year }

This loops over the MyModel Array and crates a new array of the return values with in the block (model.year).

or even shorter code, but first calling everything from db:

@foo = MyModel.all.map(&:year)
jigfox
Could you explain this please?
yuval
hope my update helps to understand
jigfox
A: 

You can use map to change every value in an array. Example:

@foo = MyModel.find(:all, :select => 'year').map { |model_object| model_object.year }
hundredwatt
you need to put a dot between `'year')` and `map!`, and why do you use `map!`, `map` would just work fine here, because your assigning the result to a new variable
jigfox
Good catch. I edited it to use `map`.
hundredwatt
+1  A: 

If you don't want to instantiate models, you'd do it this way:

MyModel.connection.select_values("SELECT year FROM my_models")

This will return an Array of String objects. Then you can transform using Ruby tools as you see fit.

François Beausoleil