What's the best way to model this?

Let's say I have a user model and a contacts model (contacts contains
name, phone number, email, etc. of people that the user knows). The
models would be

User:

has_many :contacts

Contact:

belongs_to :user

Now let's say I wanted to introduce groups, where the user could place
certain contacts into groups. Some contacts would be in multiple
groups, others wouldn't be in groups at all. What would be the best
way to model this?

I was thinking

User:

has_many :contacts
has_many :groups

Groups:

belongs_to :user
has_and_belongs_to_many :contacts

Contacts:

belongs_to :user
has_and_belongs_to_many :groups

But I'm not sure if this really works. How can I guarantee that a
contact in a group really belongs to the user (maybe I can't through
the model and need to do it in code but that seems so unRails like).

Dale

Any ideas?

Hi there,

The way I would do it would be like,

Groups:

has_and_belongs_to_many :users

Users:

belongs_to :group
has_and_belongs_to_many :contacts,
           :class_name => 'User',
           :join_table => 'user_contacts',
           :association_foreign_key => :contact_id,
           :foreign_key => :user_id,
           :after_add => :make_contact_to_contact,
           :after_remove => :remove_my_contact

with

  # I am there contact so they are my contact
  def make_contact_to_contact(contact)
    contact.contacts << self unless contact.contacts.include?(self)
  end

  # Ok lets no be friends any more :frowning:
  def remove_my_contact(contact)
    contact.contacts.delete(self) rescue nil
  end

In the above I take it that a contact is just another User, hence the
user_contact table.

With the above the Group is at the top so you could have something like

user = User.find(:first)

user.groups.first.users --> gives all the users from that users first
group, if you get what I mean.

Karl

Karl,

Thanks for the response but actually contacts are not other users - I
should have made that clearer. Rather than it being a social-graph
type application, it's more like contact management, so contacts
belong to the user but are not associated with other users in any way.
If they were, your implementation makes perfect sense, but we're
actually dealing with 3 models here not 2.

Dale