您如何使用自引用和类别对联系人列表进行建模?

时间:2012-05-11 08:44:58

标签: ruby-on-rails model self-reference

摔跤我的头脑模型

  1. 用户有多个联系人类别(家人/朋友)
  2. 一个联系人类别有很多联系人
  3. 一个联系人可以是一个或多个联系人类别。
  4. 我最终会跟随,但我仍然相信,必须有更好的解决方案。

    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 个答案:

答案 0 :(得分:6)

假设

  • 这是一个适用于许多用户的系统,而不仅仅是一个系统,因此您需要使用外键在联系人和组记录上指定所有者。
  • 联系人可以属于多个群组,群组有多个联系人,因此这是一个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表创建一个Model,因为我们不会直接访问它,而只会通过Contact或Group访问它。

结果

这将允许您执行以下操作:

@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 id和Group id传递给一个控制器动作,然后在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_idgroup_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_idgroup_id传递给控制器​​操作,然后控制器操作就会有足够的信息来执行此操作。

答案 1 :(得分:2)

您可以使用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

这将有效。