# Database design question

**URL:** <https://www.ruby-forum.com/t/database-design-question/137282>\
**Category:** Rails\
**Created:** [May 11, 2008, 11:54am UTC](https://www.ruby-forum.com/t/database-design-question/137282 "2008-05-11T11:54:40Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ANSS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d78d45/32.png) [@ANSS](https://www.ruby-forum.com/u/ANSS)\
**Post date:** [May 11, 2008, 11:54am UTC](https://www.ruby-forum.com/t/database-design-question/137282/1 "2008-05-11T11:54:40Z")

</div>

Hello,  
I need your advice regarding the following situation:

In my application I already have a Users table, now I need to add an  
address  
book for each user to save his/her contacts, I need also to add the  
possibility for the user to create groups out of his contacts. As for  
now I  
think of the following design:  
3 models: User, Address, and Group

User has\_many addresses  
Address belongs\_to User

User has\_many groups  
Group belongs\_to User

Group has\_many addresses  
Address belongs\_to Group

Is this a (healthy) design? Is it better to create a join table?

Your suggestions are highly appreciated 🙂

–  
Anas Marrawi  
Visit me at: [www.anasonline.net](http://www.anasonline.net)

If you want to send me encrypted emails. My public key: pub:13427489:17

---

<div class="post-metadata">

**Author:** ![ANSS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d78d45/32.png) [@ANSS](https://www.ruby-forum.com/u/ANSS)\
**Post date:** [May 11, 2008, 1:09pm UTC](https://www.ruby-forum.com/t/database-design-question/137282/2 "2008-05-11T13:09:51Z")

</div>

AN@S wrote:

> User has\_many groups  
> Group belongs\_to User
> 
> Group has\_many addresses  
> Address belongs\_to Group
> 
> Is this a (healthy) design? Is it better to create a join table?

The great thing about migrations (and unit tests) is you are not stuck  
with your  
answers. You can deploy, change your database, and deploy again, without  
asking  
your users to re-input all their data.

A group has a name, for your user to tag contacts with. So if an  
implicit “join  
table” (for has\_and\_belongs\_to\_many) can’t have any attributes, you need  
an  
explicit one.

However, your current system is not dry. Users have many Groups, and  
Groups have  
and belong to many Addresses. If you supply one anonymous Group per User  
(to  
hold the Contacts that a User has not yet aligned with any Groups, then  
you  
don’t need Addresses that belong to Users and Groups at the same time.  
Multiple  
ownership is bad like Matrix Management; Contacts should only belong to  
Groups.

User 1–\>\* Group _\<–\>_ Contact

User.has\_many :groups  
Group.belongs\_to :user  
Group.has\_and\_belongs\_to\_many :contacts # and migrate contacts\_groups  
Contact.has\_and\_belongs\_to\_many :groups  
User.has\_many :contacts, :through =\> :groups  
Contact.has\_one :user, :through =\> :groups

Now report back if the last two lines work. I have never gotten a  
:through  
working with a habtm! If they don’t work, trivially write accessors to  
do the  
same things:

class User  
def contacts  
groups.map(&:contacts).uniq  
end  
…

And remember to create one anonymous Group each time you create a User.

–  
Phlip

---

<div class="post-metadata">

**Author:** ![ANSS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d78d45/32.png) [@ANSS](https://www.ruby-forum.com/u/ANSS)\
**Post date:** [May 11, 2008, 6:10pm UTC](https://www.ruby-forum.com/t/database-design-question/137282/3 "2008-05-11T18:10:47Z")

</div>

> class User  
> def contacts  
> groups.map(&:contacts).uniq

groups.map(&:contacts).flatten.uniq # !

> end

New question: how to write that expression without stomping the database  
once  
per group, and loading the popular contacts more than once?

---

<div class="post-metadata">

**Author:** ![ANSS](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d78d45/32.png) [@ANSS](https://www.ruby-forum.com/u/ANSS)\
**Post date:** [May 12, 2008, 1:53am UTC](https://www.ruby-forum.com/t/database-design-question/137282/4 "2008-05-12T01:53:20Z")

</div>

Phlip wrote:

> > class User  
> > def contacts  
> > groups.map(&:contacts).uniq
> 
> groups.map(&:contacts).flatten.uniq # !
> 
> > end
> 
> New question: how to write that expression without stomping the database  
> once  
> per group, and loading the popular contacts more than once?

when you load your user;

@user = User.find(params[:id], :include =\> {:groups =\> :contacts})
