0

What's the best way to work with double plurals in Rails? I've got a few has_and_belongs_to_many relationships, and I want something like:

@templates = current_user.brands.templates

But the closest I can do is something like this:

current_user.brands.each do |b|
  @templates = b.templates
end

Any thoughts?

t56k
  • 6,769
  • 9
  • 52
  • 115

2 Answers2

2

You can use through association in user model.

class User < ActiveRecord::Base
  has_many :templates, :through => : brands
  ....
end

Then,

@templates = current_user.templates

Or,

You can also get result by iterating over brands array and collecting templates for each brand:

@templates = current_user.brands.map{|brand| brand.templates}.flatten
Aman Garg
  • 4,198
  • 2
  • 21
  • 29
  • That's good but it ignores duplicates (i.e., if two `brands` have access to the same template). – t56k Aug 06 '13 at 04:49
  • @emm: but why do you want duplicate records to appear twice having same id. – Aman Garg Aug 06 '13 at 05:03
  • It's about access: a user can have many brands, and brands can have many templates (some are the same). So users should be able to access all the templates their brands can without any duplication. – t56k Aug 06 '13 at 05:05
  • are using has_and_belongs_to_many relationship between User and Brand. – Aman Garg Aug 06 '13 at 05:14
  • I am, yeah, but I don't have to. – t56k Aug 06 '13 at 05:17
  • through association will always find distinct records. The converted query for current_user.templates will be "SELECT DISTINCT `templates`.* FROM `templates` INNER JOIN `brands` ON `templates`.`id` = `brands`.`template_id` WHERE `brands`.`user_id` = 1". So if u want duplicate records also, use current_user.brands.map{|brand| brand.templates}.flatten – Aman Garg Aug 06 '13 at 05:30
1

I don't think you can have something like brands.templates. If you'd like to have a collection of templates from multiple brands, the only way to do so is to "collect" the templates from each brand you're looking through:

@templates = []
current_user.brands.each do |b|
  @templates.push(b.templates)
end

A has_and_belongs_to_many association, like a has_many association, generates the methods brand.templates and template.brands, but not brands.templates.

Amy.js
  • 536
  • 4
  • 11