Reputation: 310
This isn't another should I use HABTM or HMT question. Honest. That said, I am going to ask whether people would use HABTM or HMT in the following situation.
I already know the difference between the two assocations, I know about join tables, and I know (generally) the benefits to each association system.
Clearly I can set up two HABTM relationships here.
However, it struck me that I could also be witty and put my foreign_ids in the "Books" model table by declaring Authors and Topics as "has_many :authors/topics, :through => :books".
My question is whether people think this is an over-abstraction of the database structure, given that the primary relationship is between BOOKS and AUTHORS, and BOOKS and TOPICS, and is not the direct relationship between AUTHOR and TOPIC?
Put another way, it seemed that while I get to do away with two (extra) join tables and use the more flexible HMT relationship, I might be diluting the point of my database, which was to store BOOKS, which then link to AUTHORS and TOPICS.
I thought this was a relatively interesting question.
Also, all the other examples on the Internet I could find of the use of HMT used the "through" table as a relatively insignificant portion of the database. For example - using it as a "through" table to store grades of STUDENTS who took TESTS; - to store info about magazine subscriptions of SUBSCRIBERS who subscribed to MAGAZINES.
I've never seen an example where the "through" table stores primary information. It seems to be more for storing ancillary information about the two main tables that it joins.
Upvotes: 0
Views: 1630
Reputation: 310
I cannot do what I wanted to do; that is, put the join table in BOOKS. Why not? Because if I make BOOKS the join table, each book will have exactly one "author_id" and exactly one "topic_id". Since I want to be able to have multiple authors per book and multiple topics per book, I will have nowhere to place those relationships.
The reason why this doesn't work is that HMT allows you to create a model that can store additional information about a relationship. In my situation, that would be the relationship between a specific author and a specific topic.
A book is not an instance of this relationship.
Instead I'll need to HMT books to authors, and books to topics. THEN if I wanted to store additional information about the relationship between an author and a book, I'd have a model to store it in. That additional information might be:
and in each case you can see the information stored in the HMT model is particular to both the author and the book being joined. (So if I had multiple authors, the information about author #2<->book would be stored in a separate HMT model.)
As @dasil003 pointed out, you could kludge around this and try to store multiple relationships in one field, but then you'd probably not be able to join properly.
Upvotes: 0
Reputation: 48706
Generally, the vast majority of Rails people prefers has_many through. To tell you the truth, i think that HABTM will be removed from Rails in the versions to come. Using through is more explicit and less error prone and i strongly suggest that you use that instead. Especially, if this is the first time you create join tables in Rails.
Now, using a foreign id on books is not a good idea. You would be trying to make a many to many association using two tables and that is a very bad relational databases thing to do :) Instead, with many to many associations, stick to using has many through, that should be just fine.
(btw, belongs_to_many does not exist, you would need a third model to do that)
Upvotes: 0
Reputation: 17246
I don't know what you mean by "belongs_to_many: through Books", but both habtm and hmt use a join table. If you have a many-to-many relationship there's no getting away from it. I don't understand how you plan to store multiple authors or topics on books table. If you combine the values in a single field you won't be able to join the authors or topics. If you have a fixed maximum you could add an association field for each one, but that seems kludgy in most cases.
As for an example of primary data on a hmt relationship. Imagine that you were assuming that each topic had a specific chapter in a book (contrived I know, but it fits your model). The topic might be a different chapter in each book. In that case you would need to add the chapter field to the join table and use hmt.
Upvotes: 0