假设
- 这是一个适用于许多用户的系统,而不仅仅是一个用户,因此您需要使用外键在联系人和组记录上指定所有者。
- 一个Contact可以属于多个Group,一个Group有多个contact,所以这是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
接触模型。一个联系人属于一个所有者,我们正在为所有者关系使用“用户”模型。此外,Contact 指的是另一个用户(或属于,Rails 用语,这在这种情况下有点令人困惑),但是 :user 匹配模型的名称,所以我们不需要像我们那样指定:所有者。最后,与 Groups 的 has 和属于 many 关系。
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_id
and传递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
and传递group_id
给控制器动作,然后控制器就有足够的信息来做这件事。