N<--extra_column-->n relationships

I’m moving the company’s article service (currently a PHP site) to Ruby
on Rails, and here’s where I bump into trouble:

We sell candy in multiple flavours, and they come in two different
packages. Here’s the (fleshed out) database model:

flavours

*id
name

packs

*id
volume

flavours_packs

flavour_id
pack_id
article_number

This yields an n<->n relationship between flavours and packs: One
flavour can come in many package sizes, and one package type can carry
multiple flavours.

The reason behind this design is that each combination of flavour and
package has a unique article_number.

So far so good. My problem is that I don’t know how to access the
article_number field. When listing the flavours (flavours/list.rhtml) I
want to display each flavours article number for the different package
sizes, like:

Flavour 20-pack 100-pack
Vanilla 99021 99101

This is as close as I get:

<% for flavour in @flavours %>

<% for column in Flavour.content_columns %> <%=h flavour.send(column.name) %> <% end %> <% for pack in @packs %> <%= DISPLAY THE ARTICLE NUMBER FOR THIS PARTICULAR COMBINATION OF FLAVOUR/PACK %> <% end %> <% end %>

Am I approaching this the wrong way? Should I instead create a virtual
model incorporating both flavours, packs and article numbers? How?

I’d be very grateful for any insights,

/ Vincent

Yup, you need a third model, maybe FlavorPack, and a ‘has_many :through
=>’ relationship.

http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off

On 10/6/06, Vincent [email protected] wrote:

*id

package has a unique article_number.

So far so good. My problem is that I don’t know how to access the
article_number field. When listing the flavours (flavours/list.rhtml) I
want to display each flavours article number for the different package
sizes, like:

Flavour 20-pack 100-pack
Vanilla 99021 99101

You are describing a “has_many :through” relationship.

class FlavoursPacks < ActiveRecord::Base
belongs_to :flavour
belongs_to :pack
end

class Flavour < ActiveRecord::Base
has_many :flavours_packs
has_many :packs, :through => :flavours_packs
end

class Pack < ActiveRecord::Base
has_many :flavours_packs
has_many :flavours, :through => :flavours_packs
end

Then you can access flavours_packs from either direction and call
methods on those objects.

somePack.flavours_packs[0].article_number

– James

Thanks a lot for you answers, you really helped me out.
I’ve made an implementation which works, but it’s dead ugly and I fear
I’m writing in Ruby but (still) thinking in PHP.

I would really appreciate if anyone would optimize/point out the
particularly unsexy parts of the following:

The VIEW (which prints “Vanilla 99021 99101”)

<% for flavour in @flavours %>

<% for column in Flavour.content_columns %>
<%=h flavour.send(column.name) %>
<% end %>

<% for pack in @packs %>
<%= flavour.artno(pack.id) || “—” %>
<% end %>

<% end %>

The artno-function of the MODEL

def artno(pack_id)
art = self.flavours_packs.find(:first, :conditions => [“pack_id =
?”, pack_id])
if (art)
return art.artno
end
end