Ruby Forum Ruby on Rails > Database design question

Posted by AN@S (Guest)
on 11.05.2008 11:54
(Received via mailing list)
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

If you want to send me encrypted emails. My public key: pub:13427489:17
Posted by Phlip (Guest)
on 11.05.2008 13:09
(Received via mailing list)
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
Posted by Phlip (Guest)
on 11.05.2008 18:10
(Received via mailing list)
> 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?
Posted by Matthew Rudy Jacobs (matthewrudy)
on 12.05.2008 01:53
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})