Reputation: 6882
I have read the Choosing Between has_many :through
and has_and_belongs_to_many
on the Rails website, however I am a bit confused since I have a different case to the ones given on the website.
I have two models: Prop
and CharacterCostume
, and the character's costume can have multiple props associated to it, but a prop doesn't belong to that character and it can be used by any number of characters in the scene, too.
Right now I have has_and_belongs_to_many :props
inside my CharacterCostume
model, which does exactly what I want it to do: it fetches all the props associated with the costume using a table named character_costumes_props
when I call CharacterCostume#props
However the association name is putting me off because of the "belongs to many" part. The costume does not belong to any of the props, so there's no has_and_belongs_to_many :character_costumes
inside the Prop
model.
I know that it can all function fine without it, but it got me thinking that maybe I should use a has_many :through
association, but that requires me to create a superfluous model (it is superfluous, right?) and the model would look like this:
class CharacterCostumeProp < ActiveRecord::Base
belongs_to :character_costume
has_one :prop
end
Also, would has_one
instead of belongs_to
work here?
I want the code to be as semantic as possible, but I am not sure if this will increase the requirement for resources or decrease performance in some way, since there's an intermediate model.
Are there certain quirks/benefits attached to either approach? Is mine good enough? Or is my thinking completely wrong from what I need to do?
Thanks!
Upvotes: 1
Views: 1432
Reputation: 5803
I think you want to use a :has_many, :through
because you're going to want to work directly with the relation model - what scene(s), consumed or damaged, etc.
But, the reason it reads funny to you is that, for the most part, has_many
and belongs_to
don't really mean what they mean in English. What they really mean is "They have the foreign keys" and "I have the foreign key", respectively; the exception being the :dependent => :destroy
behavior.
That still doesn't really help with has_and_belongs_to_many
, since you're then saying, "They have the foreign keys and I have the foreign keys` - except that you can think of it sort of adding a new part both to "I" and "They" that happens to be the same part for each, and has those keys.
Does that help?
Upvotes: 2
Reputation: 29281
The single most important question you must ask yourself when deciding between HABTM and has_many :through
is this:
Do I want to store any information specific to the association?
A many-to-many relationship between readers and magazines might conceivably be structured as a HABTM or a has_many :through
. However, the latter makes far more sense in this case because we can easily think of information specific to the association that we might want to store.
A reader is related to a magazine through a subscription, and every subscription can be described by fields such as price, starting date, issue frequency and whether it's active or not.
The relationship between an existing Tag
model and, say, an Article
model is clearly of the many-to-many kind. The fact that one particular tag has been associated to any particular article must have no influence on whether the same tag will be able to be similarly associated to other articles in the future.
But, differently from the previous example, here the association itself is all the information we need. We just need to know which tags are associated to any given article. It doesn't matter when the association was formed. It doesn't matter how long it lasted.
It may matter to us how many articles a tag is associated with. But that information is stored in the Tag
model since it's not specific to an association. There is even a Rails feature that takes care of that called counter_cache
.
Upvotes: 2
Reputation: 2495
has_one
wouldn't work, you'd need belongs_to
See example below
class Student
has_and_belongs_to_many :courses
has_many :teachers, through: :courses
end
class Teacher
has_many :courses
has_many :students, through: :courses
end
class Course
has_and_belongs_to_many :students
belongs_to :teacher
def boring?
teacher.name == 'Boris Boring'
end
end
In the example above, I make use of both versions. See how Course would have its own logic? See how a class for CourseStudent might not? That's what it all comes down to. Well, to me it is. I use has_many through
for as long as I can't give a proper name to my association model and/or the model doesn't need extra logic or behavior.
Upvotes: 0