Rails 4自我引用多对多关系

时间:2015-12-03 23:23:45

标签: ruby-on-rails ruby ruby-on-rails-4

我无法解决这个问题,任何帮助都会受到赞赏。我在这里浏览了很多文章和其他帖子,我似乎无法得到我正在寻找的结果。

我有一个用户模型和团队模型。

Team Model有 user_id team_id

创建团队的用户将是user_id,团队成员的用户将在team_id中

User Model
 has_many :teams, foreign_key: :team_id
 has_many :team_members, class_name: "Team", foreign_key: :user_id

Team Model
 belongs_to :user, foreign_key: :team_id    
 belongs_to :team_member, class_name: "User", foreign_key: :user_id

我努力实现的最终结果是:

  • 每个用户都可以添加任意数量的团队成员
  • 每个用户都可以看到属于他们团队的用户列表。
  • 一个视图,作为团队成员的用户可以看到他们所属的团队。

1 个答案:

答案 0 :(得分:0)

我相信你要找的是join table model。问题在于UserTeam可能彼此有很多。所以这种关系必须单独存储。

在此类似问题上查看此答案:https://stackoverflow.com/a/15442583/5113832

因此,您可以选择UserTeamTeamMembership的模型结构。

更新以在销毁用户或团队时销毁相关团队成员资格。

#app/models/user.rb
class User < ActiveRecord::Base
  has_many :team_memberships, :dependent => :destroy
  has_many :teams, :through => :team_memberships
end

#app/models/team.rb
class Team < ActiveRecord::Base
  has_many :team_memberships, :dependent => :destroy
  has_many :users, :through => :team_memberships
end

#app/models/team_membership.rb
class TeamMembership < ActiveRecord::Base
  belongs_to :user
  belongs_to :team
end

更新了以回复问题:

  

我的控制器如何看待创建? (将用户添加到团队中) - 迈克尔

为了将用户添加到团队中,您可以在UserController中执行此操作,您可以在TeamController中执行此操作。但是,由于您现在正在创建TeamMembership资源,因此您需要在TeamMembership中创建TeamMembershipsController条记录。这与&#34; Rails&#34;做事的方式。例如:

# app/controllers/team_memberships_controller.rb
class TeamMembershipsController < ApplicationController
  def index
    @team_memberships = TeamMembership.all
  end

  def new
    @team_membership = TeamMembership.new
  end

  def create
    @team_membership = TeamMembership.new(team_membership_params)
    if @team_membership.save
      flash[:success] = 'Team membership created'
      redirect_to team_memberships_path
    else
      flash[:error] = 'Team membership not created'
      render :new
    end
  end

  def destroy
    @team_membership = TeamMembership.find_by_id(params[:id])
    if @team_membership && @team_membership.destroy
      flash[:success] = 'Team membership destroyed'
    else
      flash[:error] = 'Team membership not destroyed'
    end
    redirect_to team_memberships_path
  end


  private
  def team_membership_params
    params.require(:team_membership).permit(
      :user_id,
      :team_id
    )
  end
end

拥有TeamMembership资源的好处是使用此模式来管理从团队添加(#create)或删除(#destroy)用户的时间。

Rails associations的神奇之处在于为这些模型的每个实例访问团队成员(用户)和用户团队。

您只需针对这些资源开展CRUD业务,Rails会根据您的惯例为您处理组织。

此外,我更新了原始模型代码,以便在用户或团队被销毁时销毁团队成员资格。这样可以确保team_memberships表中没有orphaned records

作为最后的说明。您还应该能够轻松使用form_forTeamMembership发送到您要创建的控制器。这可以通过使用Rails&#39;的用户和团队的选择选项下拉菜单来完成。 collection_select

<%# app/views/team_memberships/new.html.erb %>
<h1>
  Create Team Membership
</h1>

<%= form_for(@team_membership) do |f| %>
  <%= f.label(:user) %>
  <%= f.collection_select(
    :user_id,
    User.all,
    :id,
    :username
  ) %>

  <%= f.label(:team) %>
  <%= f.collection_select(
    :team_id,
    Team.all,
    :id,
    :name
  ) %>

  <%= f.submit %>
<% end %>

以上代码将为所有用户和团队提供下拉列表,允许您选择特定组合以创建团队成员资格。删除团队成员资格与发送团队成员DELETE #destroy的{​​{1}}请求一样简单。

另一个考虑因素可能是在迁移和模型验证中向数据库表和模型添加unique pair constraint

希望这有帮助!