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

3

建模如下:

  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个回答

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

创建Groups表。同时为所属用户创建一个外键。
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 术语中属于,这在这种情况下有点混乱),但是 :user 匹配模型的名称,因此我们不需要像对 :owner 做的那样指定它。最后,与组之间存在多对多的关系。

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表创建一个模型,因为我们不会直接访问它,而是只会通过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评论询问添加联系人到分组的视图是什么样子。

实际上有很多不同的方法可以实现这一点,但总体思路是您需要将联系人id和分组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到控制器操作中,然后该操作将具有足够的信息来执行其任务。


太棒了 Rico!在某些情况下比啤酒更好(:-))非常感谢你! - Jakub Kuchar
这在视图中会是什么样子? - benrmatthews
我不确定你在问什么,@benrmatthews。你能告诉我你在视图中想要实现什么吗? - Richard Jones
@toasterlovin 如果我想要在联系人展示页面上将其添加到一个分组中,应该怎么做? - benrmatthews
@benrmatthews 我已经添加了将联系人添加到群组的路由/控制器/视图逻辑。祝你使用愉快! - Richard Jones
感谢 @toasterlovin! - benrmatthews

2
你可以使用has_many :through关联。
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

这将有效。


谢谢您的迅速回复。但是我想将Contact模型保留为对User模型的引用,因为这是一种社交网络,用户只会从User模型中添加联系人,而不会从其他地方添加。在Contact类中添加belongs_to:user是否可以解决我的问题? - Jakub Kuchar
我正在根据你的情况更新上面的答案,采用新的结构,我认为这样会更好。 - abhas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接