(ActiveRecord) Why is there no "belongs_to_many"?

Hello, I am re-opening this again, sorry :).

I have just read in RailsGuides ( Active Record Associations — Ruby on Rails Guides ) about the proper way to choose between belongs_to and has_one. From this point of view, something like belongs_to_many seems to be really missing, but i do not know if maybe there is a better name, and how to call the other side of the association (has_a ?). I am talking about something like this:

class Member < ActiveRecord::Base   has_an :address end

class Address < ActiveRecord::Base   belongs_to_many :members end

Different members can have the same address, if they are a couple for example.

This can me implemented the same way as has_and_belongs_to_many, except that in the joint table the Foreign Key for Members must be required to be unique.

An Address can be then automatically deleted when the last Member living at that address is deleted.

The advantage over [belongs_to, has_many] is the same as for has_one over belongs_to: the Members table does not need to "know" about the Addresses table.

Hello, I am re-opening this again, sorry :).

I have just read in RailsGuides (

http://guides.rubyonrails.org/association_basics.html )

about the proper way to choose between belongs_to and has_one.

From this point of view, something like belongs_to_many seems to be

really missing, but i do not know if maybe there is a better name, and

how to call the other side of the association (has_a ?).

I am talking about something like this:

class Member < ActiveRecord::Base

has_an :address

end

class Address < ActiveRecord::Base

belongs_to_many :members

end

Different members can have the same address, if they are a couple for

example.

This can me implemented the same way as has_and_belongs_to_many, except

that in the joint table the Foreign Key for Members must be required to

be unique.

An Address can be then automatically deleted when the last Member living

at that address is deleted.

The advantage over [belongs_to, has_many] is the same as for has_one

over belongs_to: the Members table does not need to “know” about the

Addresses table.

The thing is, this would just duplicate existing associations; I don’t see how it’s needed. The relationship you describe above can be written much simpler (no join table at all) by just having User belongs_to :address, and Address has_many :users.

If it’s the readability of the code that you want, you can always do things like

class Address << ActiveRecord::Base

has_many :residents, :class_name => “User”

end

class User << ActiveRecord::Base

belongs_to :address, :foreign_key => “resident_id”

end

For many-to-many, I really tend to favor has_many :through associations from both sides, as they’re more flexible.

But honestly; I don’t think belongs_to_many is missing. Just my 2¢. :slight_smile:

Can you please show the database layout you have in mind that this would map to?

The normal way would be:

User (belongs_to :address)   - id   - address_id

Address (has_many :users)   - id

If you want the user to not know about the address, you could do:

User

Addressable   - address_id   - object_id   - object_type

Address

and then user and address would both use have_* :through.

Thanks for your replies.

Probably there are ways around (i have not finished reading the RailsGuides yet), but what seems to be nice to have is:

1. not to store any foreign key in Members table, 2. have a kind of (:dependent => ...) option that would allow to automatically delete an Address when the last Member living at that address is deleted.

Adam, was your question addressed to me or to Phil?

David A. Black wrote in post #712598:

Hi --

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

I am very grateful for this response. I, too was having a bit of difficulty earlier when the "English just wasn't making sense". See, I have an Event model and a DressCode model and I want to say that Event has_one DressCode, but I put the foreign key (dress_code_id) in the Event model (just as I would in my usual SQL/PHP ways. It turned out that I had to say DressCode has_many Events and Event belongs_to DressCode. Unorthodox but it works because now I can run Event.dress_code and I get the result i'm looking for.

Rails is so advanced that I sometimes forget that it is still just a programming language and, as you said, can't always be semantically correct all the time when illustrating real world relationships.

I spent a while searching, ended up on this thread and I finally got my head around it. To the original poster - just take the advice and do what needs to be done in order to satisfy the rails convention. Reading your code might be weird, but that's nothing that a few comments can't fix :wink:

Just use a couple of aliases if you're so bothered by the lack of semantic readability.

belongs_to_many = has_many has_a = belongs_to

but beware that in your need to make the code more semantically readable, you've just confounded a seasoned railer. :slight_smile: