Как бы вы смоделировали список контактов с собственной ссылкой и категорией?

Борьба с моей головой, чтобы следовать модели

  1. У пользователя много категорий контактов (семья / друзья)
  2. Одна категория контактов имеет много контактов
  3. Один контакт может быть в одной или нескольких категориях контактов.

Я заканчиваю тем, что следую, но я все еще верю, что должно быть лучшее решение.

class User < ActiveRecord::Base  
    has_many :contact_groups  

    def get_all_contacts  
        self.contact_groups.each do |group|  
        contacts << group.users  
    end  
end  

class ContactGroup < ActiveRecord::Base  
    has_and_belongs_to_many :users  
end 

2 ответа

Решение

Предположения

  • Это система для многих пользователей, а не только для одного, поэтому вам необходимо указать владельца в записях контактов и групп с помощью внешнего ключа.
  • Контакт может принадлежать нескольким группам, а группа имеет несколько контактов, поэтому это отношение has_and_belongs_to_many.

Миграции

Создать таблицу пользователей:

class CreateUsers < ActiveRecords::Migrations
  def change
    create_table :users do |t|
      t.text :username
    end
  end
end

Создать таблицу контактов. Имеет внешний ключ для пользователя, которому принадлежит контакт, а также для пользователя, к которому относится контакт.

class CreateContacts < ActiveRecord::Migrations
  def change
    create_table :contacts do |t|
      t.references :owner
      t.references :user
    end
  end
end

Создать группу таблиц. Также имеет внешний ключ для пользователя, которому принадлежит группа.

class CreateGroups < ActiveRecord::Migrations
  def change
    create_table :groups do |t|
      t.references :owner
      t.text :name
    end
  end
end

Создайте таблицу для отношения has_and_belongs_to_many между контактами и группами. Имеет два внешних ключа; один для контакта, а другой для группы.

class CreateContactsGroups < ActiveRecord::Migrations
  def change
    create_table :contacts_groups do |t|
      t.references :contact
      t.references :group
    end
  end
end

модели

Пользовательская модель. У пользователя много контактов, и внешний ключ в таблице контактов, который связывает контакт с пользователем, - это столбец owner_id. То же самое для групп.

class User
  has_many :contacts, :foreign_key => 'owner_id'
  has_many :groups, :foreign_key => 'owner_id'
end

Контактная модель. Контакт принадлежит Владельцу, и мы используем модель "Пользователь" для отношений Владельца. Кроме того, Контакт относится к другому Пользователю (или относится к языку Rails, что в некоторой степени сбивает с толку), но: пользователь соответствует названию модели, поэтому нам не нужно указывать то, что мы делаем для: владелец. Наконец, имеет и принадлежит многим отношениям с группами.

class Contact
  belongs_to :owner, :class_name => 'User'
  belongs_to :user
  has_and_belongs_to_many :groups
end

Групповая модель. Группа принадлежит Владельцу и имеет и принадлежит многим Контактам.

class Group
  belongs_to :owner, :class_name => 'User'
  has_and_belongs_to_many :contacts
end

Нам не нужно создавать модель для таблицы contacts_groups, поскольку мы не будем обращаться к ней напрямую, а вместо этого будем обращаться к ней только через контакт или группу.

Результаты

Это позволит вам делать что-то вроде следующего:

@user.contacts # all of the user's contacts
@user.groups # all of the user's groups
@user.groups.find(id).contacts # all the contacts in a group
@user.contacts.find(id).groups # all of the groups that a contact belongs to

Добавление контактов в группу

Это в ответ на комментарий @benrmatthews, спрашивающий, как будут выглядеть представления, чтобы добавить контакт в группу.

На самом деле существует множество различных способов достижения этого, но общая идея заключается в том, что вам нужно передать идентификатор контакта и идентификатор группы в действие контроллера, которое затем создаст запись в таблице contact_groups, чтобы указать, что контакт был добавлен в группу.

Ваши маршруты могут выглядеть так:

resources :contact_groups, only: [:create]

Тогда у вас будет контроллер, который выглядит примерно так:

class ContactGroupsController < ApplicationController
  def create
    @contact = Contact.find(params[:contact_id])
    @group = Group.find(params[:group_id])
    @contact.groups << @group
  end
end

Теперь все, что вам нужно, это формы, которые проходят contact_id а также group_id к действию контроллера. Вот как это будет выглядеть:

# This is for adding the contact to a group
form_tag contact_groups_path do
  hidden_field_tag :contact_id, @contact.id
  select_tag :group_id, options_from_collection_for_select(Group.all, :id, :name)
  submit_tag "Add to Group"
end

Это создает форму со скрытым полем, которое содержит contact_id и поле выбора, которое будет отображать список имен групп. Когда эта форма будет отправлена, она пройдет contact_id а также group_id к действию контроллера, который затем имеет достаточно информации, чтобы сделать свое дело.

Вы можете использовать has_many: через Ассоциацию

class User
    has_many :contacts
    has_many :contact_groups, :through => :contacts
end

class Contact
    belongs_to :user
    has_many :contact_groups
end

class ContactGroup
    belongs_to :contacts
end

это будет работать

Другие вопросы по тегам