Rails has_and_belongs_to_many is confusing me with fixtures and factories
Asked Answered
E

1

7

General Confusion
I have bands which can have 3 genres. I read in a previous SO post that the proper way to handle this is a couple steps:

1) In band.rb

has_and_belongs_to_many :genres

2) Create a band_genres join table

Even after reading the documentation, I am a bit confused as to what HABTM actually means. I guess I would just normally think "a band has many genres", not has and belongs to many. So a quick DUMBED down explanation of that would be great.

Confusion with Fixtures

Also, when doing my fixture for band_genres I have

{ 
  "The Reaper Band and Funk": { "band": "The Reaper Band", "genre": "Funk" },
  "The Reaper Band and Rock": { "band": "The Reaper Band", "genre": "Rock" }  
}

And I get a "unknown" band column. I thought rails was supposed to know that "The Reaper Band" would refer to a band from a band fixture (same name of course) and would grab that id and know that "band" in this fixture would refer to band_id in the join table. I would rather my fixtures look like this than have hard coded numbers.

Confusion With Factories

When I create a band in my factory, I want to assign it genres:

Factory.define :band do |f|
  f.sequence(:name) { |n| "Band#{n}" }
  f.mailing_lists { |mailing_lists| [mailing_lists.association(:mailing_list)] }
  f.genres 2
end

I realize here I would probably need a hard coded genre_id. But why doesn't rails look at that and say "oh, he wants to add genre with id=2 to the band_genres table".

I am not expecting rails to take care of all the dirty work for me, but I do want to play by the rules.

Ephesians answered 12/6, 2009 at 1:3 Comment(0)
H
21
  1. Has and belongs to many defines the relationship in both directions. If you only need to see what genres the band belongs to, has_many will be fine. If you want to know what bands are "funk", you can use HABTM to allow a lookup of bands for a given genre.
  2. For fixtures, in rails you can now do HABTM without creating a separate fixture for the join table. For example:

in bands.yml:

reaper_band:
  name: The Reaper Band
  genres: funk, rock

in genres.yml:

funk:
  name: Funk
  bands: reaper_band

rock:
  name: Rock
  bands: reaper_band
Hedvige answered 12/6, 2009 at 19:57 Comment(3)
Thank you for the simple explanation. However, I am getting "Mysql::Error: Unknown column 'bands' in 'field list': INSERT INTO genres (name, bands, id) VALUES ('Funk', 'The_Reaper_Band', 46)" when I try to seed. It does not seem like rails knows to look at the join table... any idea why this would happen?Ephesians
Hmm - which version of rails are you running? This functionality was added in one of the 2.x releases. So you are getting this error when you try to 'rake fixtures:load'?Hedvige
I was looking for a solution to a has_many through: relation with a join table and the information that I don't need to set fixtures for the join table, which is what was giving me headaches, was invaluable! Voting up.Suzan

© 2022 - 2024 — McMap. All rights reserved.