has_and_belongs_to_many question

Hello,

I’m new to Ruby/Rails and going through ‘Beginning Rails 4’. In chapter 6 it has me create a join table for an articles and categories table (articles_categories). In the migrate file I’ve entered this code from the book:

class CreateArticlesCategories < ActiveRecord::Migration

def change

create_table :articles_categories, :id=> false do |t|

t.references :article

t.references :category

end

end

def self.down

drop_table :articles_categories

end

end

My issue is that after I migrate this file, when I try to make an association between the article and category object (article.categories << category) it spits an error that article_id does not exist in articles_categories table. It makes sense to me since the references above do no have _id appended in the class. If I change the class to the following, creating the relationship between article and category works fine:

class CreateArticlesCategories < ActiveRecord::Migration

def change

create_table :articles_categories, :id=> false do |t|

t.integer :article_id

t.integer :category_id

end

end

def self.down

drop_table :articles_categories

end

end

My question is, how can I get the ‘t.references’ format to work so that AR looks for an ‘articles’ and ‘categories’ column, instead of the same with _id appended?

Thanks

You need to use has_many :through when working with join tables, not
has_and_belongs_to_many. The :through parameter specifies the join
table.
See this section of the Rails guide:

Hello,

My issue is that after I migrate this file, when I try to make an association between the article and category object (article.categories << category) it spits an error that article_id does not exist in articles_categories table. It makes sense to me since the references above do no have _id appended in the class. If I change the class to the following, creating the relationship between article and category works fine:

That should work - t.references should add the _id to the column name for you. What columns did this add? Are you sure you didn't run the migration before you had finished editing it?

Fred

Blaine,

Thanks for the post. The book I’m reading followed up the basic join example (many-to-many) with a ‘rich’ join (has_many :through). From what I understand there’s a scenario for both and they’re similar but there are differences. In the book’s example the articles and categories tables are ‘meeting up’ at the articles_categories table and not ‘going through’ to reference another table.

Thanks

Fred,

You made me think I might have run the migration prematurely. So far, all examples in the book have worked perfectly (I can’t say that for many books!) so it might be a layer 8 issue… I don’t remember running it before I updated the migration file, but it’s possible. If the t.references should work, I’m happy to know that at least. I’ll go back and run through another test to see if it gets the same results.

Thanks

Blaine,

Thanks for the post. The book I'm reading followed up the basic join example (many-to-many) with a 'rich' join (has_many :through). From what I understand there's a scenario for both and they're similar but there are differences. In the book's example the articles and categories tables are 'meeting up' at the articles_categories table and not 'going through' to reference another table.

HABTM joins are used for "dumb" joins, where you want a two-way relationship between two tables that does not carry any further information about its connection. Most real-world connections aren't that dumb, and so the general advice is to use a HMT connection to "educate" that join. Person -> has many Clubs -> through Membership would be a simple example. Membership can have a member type picker, a date joined, date kicked out of the club for unsportsman-like conduct, whatever other "smart" attributes the real relationship might need to carry.

Walter

Walter,

Thanks for the input. My question was only about the example in my book which indicated that the config of ‘t.references :’ would work for the ‘dumb’ join. What I found was that AR was looking for the appended ‘_id’ for the t.references config. I received a reply here that confirmed the config in the book is valid, so it was probably an issue I caused myself somewhere. I haven’t had the chance to try it again but I plan to do so tomorrow. Being new to the rails framework and ruby language I’m concerned with knowing when and how I can use certain constructs, which is why I’m picking on this particular example. Although I might not use the dumb join often, it could happen.

BR