4

I wasn't sure how to phrase it in the title, but what I'm trying to do the following. I have 2 models that have the following relationships:

class Campaign < ActiveRecord::Base
   has_many :points
end

class Point < ActiveRecord::Base
   belongs_to :campaign
end

Now, the Point model has a "locale" attribute and I want to be able to put all the "locales" of every point of a specific campaign into an array, or collection, or whatever without having to do something like

locales = Array.new
campaign.points.each do |p|
   locales << p.locale
end

I was thinking of something along the lines of campaign.points.locales. Is there some nice Rails way of doing this query, or do I just have to iterate over the collection?

Thanks for any help.

EDIT: Also because the relationship is actually a "has_many through" relationship, this method doesn't work, as I get many repeated locales if I try to iterate in that simple way. It sounds like it should be some type of join, but I'm not sure.

Pedro Cori
  • 2,046
  • 2
  • 16
  • 23

3 Answers3

7

I'd do:

campaign.points.map(&:locale)
apneadiving
  • 114,565
  • 26
  • 219
  • 213
  • I don't know why I tend to forget suggesting this nice syntax and I use it all the time. Bah :) – lucapette Sep 30 '11 at 22:28
  • In case somebody wants to know what this means: [Ruby/Ruby on Rails ampersand colon shortcut](http://stackoverflow.com/questions/1961030/ruby-ruby-on-rails-ampersand-colon-shortcut) – slhck Sep 30 '11 at 22:47
  • The l33t oozes out of this syntax, melting all pythonistas in its path. – jimworm Sep 30 '11 at 22:55
  • 1
    Adding `.uniq!` eliminates duplicates as well: `campaign.points.map(&:locale).uniq!` – Kevin Bedell Oct 01 '11 at 05:01
4
campaign.points.map {|p| p.locale}

should do the trick.

lucapette
  • 20,564
  • 6
  • 65
  • 59
1

You could do what those guys said. Put a .uniq at the end of them and end up with the correct solution, or;

let me lead you astray with ActiveRecord fun (and possibly failure, since I can't test to see if it works here). But you'll be able to run campaign.points.locales just like you wanted.

class Campaign < ActiveRecord::Base
  has_many :points do
    def locales
      select('DISTINCT(locale)').map(&:locale)
    end
  end
end
jimworm
  • 2,731
  • 18
  • 26
  • The `.uniq` did the trick for the duplicates. Thank you very much! – Pedro Cori Sep 30 '11 at 23:10
  • Went away to read the docs in the meantime... Aww I was hoping you'd try the AR solution so I can see if it worked. I promise you time and space benefits (because it only loads the locale column in distinct records from the db)! – jimworm Sep 30 '11 at 23:26