(ActiveRecord) Why is there no "belongs_to_many"?

Hi all,

My apologies, but I am just starting with Rails. I'm curious as to why
there is no "belongs_to_many" as opposed to the current need to
contruct a relationship that basically means the same thing with more
steps.

Any ideas?

Regards,
Mike.

Hi --

Hi all,

My apologies, but I am just starting with Rails. I'm curious as to why
there is no "belongs_to_many" as opposed to the current need to
contruct a relationship that basically means the same thing with more
steps.

If you have an X that belongs to a Y, that means you'll have a y_id
field in the xs (plural of x) table.

If the X belongs to more than one Y, you have to have multiple y_id
fields for each record. Since the xs table can only have one y_id
column, you have to put the multiple y_ids in a separate table. Each
row in that table also gets the corresponding id key from the xes
table.

David

Check out this diagram:

http://mboffin.com/stuff/ruby-on-rails-data-relationships.png

It might make the relatioships a bit clearer.

--Dylan

Hi --

Hi Ashley,

Ashley Thomas wrote:

has_one|many creates methods based on the assumption that the other model has a field referencing this model, and belongs_to creates methods based on the assumption that this model has a field referencing the other model. So a belongs_to_many macro would create methods based on the assumption that this model has (infinitely) many fields referencing the other model -- which is more easily implemented with a join table, thus habtm or has_many :through.

Nice explanation.

Best regards,
Bill

I understand, but what if I don't necessarily want "both ways"? For
instance, in the Oreilly book "Ruby on Rails: Up and Running" they have
the example of a Slideshow. The Slideshow has_many Slides, and Photos
has_many Slides, but Slides belongs_to both Slideshow and Photos.
Despite how the items are defined, in English this doesn't seem
correct. It seems more likely that, if nothing else, Photos
"belongs_to_many" Slides, more than Photos "has_many" Slides, like so:

Slideshow has_many Slides
Slide has_one Photo
Slide belongs_to Slideshow
Photo belongs_to_many Slides

I don't see any need for HABTM, simply, BTM. What am I missing?

Thanks,
Mike

Daniel Waite wrote:

Hi --

Daniel Waite wrote:

gberz3 wrote:

I'm curious as to why
there is no "belongs_to_many" as opposed to the current need to
contruct a relationship that basically means the same thing with more
steps.

There is. It's called has_and_belongs_to_many. :slight_smile:

Besides that, "belonging to many" is merely the flip side of having
many. You can't truly belong to many without also having many.

Have implies a direct ownership, and belongs implies being owned. HABTM
goes both directions.

I understand, but what if I don't necessarily want "both ways"? For
instance, in the Oreilly book "Ruby on Rails: Up and Running" they have
the example of a Slideshow. The Slideshow has_many Slides, and Photos
has_many Slides, but Slides belongs_to both Slideshow and Photos.
Despite how the items are defined, in English this doesn't seem
correct. It seems more likely that, if nothing else, Photos
"belongs_to_many" Slides, more than Photos "has_many" Slides, like so:

Slideshow has_many Slides
Slide has_one Photo
Slide belongs_to Slideshow
Photo belongs_to_many Slides

I don't see any need for HABTM, simply, BTM. What am I missing?

I'm not sure I follow. It looks like it's just one-to-many, not
many-to-many, so it's not a real test of whether habtm might be
useful.

Remember too that the "have/belong" wording is really for the purpose
of establishing object-relational mappings, not fully documenting the
application. The available relations -- has_one, has_many, etc. --
will never accurately describe what's going on in every domain. You'd
really want to say:

   class Slide < AR::Base
     has_been_made_from :photo

or something like that, but we can't :slight_smile: The have/belong thing is a
simple mechanism that really just bootstraps a more semantically rich
one.

I also don't see a way to implement belongs_to_many, in database terms
consistent with ActiveRecord's logic. Where would you put the foreign
keys?

David

Basically, I'd say this:

class Photo < AR::Base
      belongs_to_many :slides
end

. . .and perhaps the following if AR couldn't figure it out

class Slide < AR::Base
      has_one :photo
end

. . .and AR should know to put the FK into Slides. Does that make
sense?

Mike

dblack@wobblini.net wrote:

sorry to reopen this but it is a valid issue that has not been taken
care of. Also, you guys simple don't get it. From the back end point of
view belongs_to_many/has_one is identical to
has_many/belongs_to------its the semantics that are different, and
simple saying that has_many sets certain things totally skips the
meaning of the words. in the from the data side
belongs_to_many-has_one==has_many-belongs_to but the switch in syntax
and semantics is key, for beauty, understandability, and overall
pleasantness. this relationship has many, many cases and its very ugly
to be forced to put it backwards.

adding belongs_to_many/has_one is in the core the same as
has_many/belongs, (the key will be in the has_one) and there is nothing
hard about it

this semantic change is cimple yet greatly usefull and intuitive, and
besides ignorance to its simplicity there is no reason why it shouldnt
be included soon into ActiveRecord

has_and_belongs_to_many. Use it.

Ryan Bigg wrote:

has_and_belongs_to_many. Use it.

but then an unnecessary intermediary table is created

Ryan Bigg wrote:

has_and_belongs_to_many. Use it.

but then an unnecessary intermediary table is created

So you don't want a join table, in which case there is only one place
the foreign key can sit.
Taking your example from your other thread, the foreign key has to sit
on the os table, which in the rails world means
that os belongs_to hardware.

If I understand you correctly what you want from the point of view of
functionality is hardware has_many oses, and os belongs_to hardware,
but you prefer to think of it as hardware belongs_to_many oses
You could just alias has_many to belongs_to_many if it will help you
out.

Fred

When I read "Also, you guys simple don't get it." I had to chime in
here at the irony.

Don't confuse Rails' use of English for handy distinctions between
has_many and belongs_to with Rails enforcing real-world distinction
between them. They are essentially the same association with the
primary distinction being which model/table holds the primary key.
There is absolutely no need to create another variant of this
association just to please what seems to be a desire for Ruby to match
English one-to-one. And if you _must_, alias_method is just a few
keystrokes away.

RSL

Hi --

David A. Black wrote:

Hi --

Ryan Bigg wrote:

has_and_belongs_to_many. Use it.

but then an unnecessary intermediary table is created

I don't seem to have received your original post, but the basic answer
is: since belonging to is expressed by a foreign key column, if you
belong to many, you'd need multiple columns called thing_id (or
whatever) in your table, and that's impossible.

David

--

but you can store the key in the has_one table's columns

it makes it so that in your forms and refrences you dont have to put a
'prefix' on everything in a form to add one small thing that happens to
have this relationship

It's a design decision and it has been made the naming convention.
Where's the problem?

If you want to, go ahead and implement belongs_to_many.

Stefan Buhr wrote:

It's a design decision and it has been made the naming convention.
Where's the problem?

If you want to, go ahead and implement belongs_to_many.

I just don't know that much ruby to do it right. But t seems like not to
hard to implement by someone who know how to---however it has to be
imamented, and only work as a pair belongs_to_many with has_one, and as
a special case as such. Do you guys understand how it works? Its
implementation would be quite useful, its ugly to use a refrence table
thats completely unnecciary.

Well as other people have said, you could just alias has_many to belongs_to_many and has_one

class ActiveRecord::Base
   class << self
     alias_method :belongs_to_many, :has_many
   end
end

Your belongs to many cannot work with the existing has_one: with your belongs_to_many the foreign key has to exist on the other table, and with has_one the foreign key also has to work on the associated table. When you've got a pair of relations, one of them has to be a belongs_to and the other one a has_many/has_one (even if you call them something else).

Fred

Your belongs to many cannot work with the existing has_one: with your
belongs_to_many the foreign key has to exist on the other table, and
with has_one the foreign key also has to work on the associated
table.
When you've got a pair of relations, one of them has to be a
belongs_to and the other one a has_many/has_one (even if you call
them
something else).

Fred

yes, i tried to say that above: belongs_to_many/has_one is a synonym
for
has_many/belongs_to and is only syntattically differnt, the has_one
oculd be called has_helper or has_utility (thats the items that fit
into
this relationship) to fix that problem.

Then just alias the methods as I showed.

Fred

Hi --

Stefan Buhr wrote:

It's a design decision and it has been made the naming convention.
Where's the problem?

If you want to, go ahead and implement belongs_to_many.

I just don't know that much ruby to do it right. But t seems like not to
hard to implement by someone who know how to---however it has to be
imamented, and only work as a pair belongs_to_many with has_one, and as
a special case as such. Do you guys understand how it works? Its
implementation would be quite useful, its ugly to use a refrence table
thats completely unnecciary.

The has/belongs semantics are, indeed, not always a perfect fit for
the way things relate when we describe them in English. For example, I
remember coming up with an example once where I ended up with a Club
belonging to a Member (or something like that; I'm not remembering
exactly), whereas normally we'd say "He belongs to that club."

My advice would be to use it as is for a while. If you want two-way
has_many's, then just use has_many. Remember that the main point of
associations, in any case, is that they generate methods for you. It's
nice to have them as close as possible to the domain you're modeling,
but it's often not very close since "has" and "belongs to" are not
general terms for expressing every possible connection between two
things.

In the end, I think it's better to keep the number of association
methods down, partly because it helps when it comes to learning how
the associations themselves behave -- which ones trigger automatic
saves, and when, and things like that.

David