【问题标题】:Additional Foreign Key on a Join Table连接表上的附加外键
【发布时间】:2016-03-31 04:16:26
【问题描述】:

我有一个连接表,连接一个客户端和一个 Setor(复数:setores)模型。关系是一个 Client has_and_belongs_to_many Setores(有三个 Setores,一个 Client 可以有一个到所有三个。Setores 有很多客户)。

我的问题是: 在这个连接表中,我添加了对 User 模型的引用。 Setores 有很多用户,但是一个客户和一个 setor 之间的关系只有一个用户。但我不知道如何在clients_setores 表上读写这个关联

我的模型如下:

class Client < ActiveRecord::Base
has_and_belongs_to_many :documents
has_and_belongs_to_many :setores
has_many :screenings
has_many :contacts
has_many :interactions, through: :contacts
validates :cnpj, uniqueness: true


class Setor < ActiveRecord::Base
  self.table_name = 'setores'
  has_many :documents
  has_many :screenings
  has_many :users
  has_and_belongs_to_many :clients
  attr_acessor :user_id


class User < ActiveRecord::Base
has_one :setores
has_many :clients

并且当前正在工作的连接表参数在客户端控制器的末端显示如下:

  private
# Use callbacks to share common setup or constraints between actions.
def set_client
  @client = Client.find(params[:id])
end

# Never trust parameters from the scary internet, only allow the white list through.
def client_params
  params.require(:client).permit(:cnpj, :pacote, :razsoc, :vencimento, user_ids:[], document_ids:[], setor_ids:[])
end

请注意,“user_ids:[]”是我试图让它工作的尝试,但到目前为止失败了。

在视图中,我使用这样的当前连接表(取自 /client/_form.html.erb):

<%= f.collection_check_boxes :setor_ids, Setor.where(pacote: true), :id, :setor do |b| %>

因此,通过这些复选框,我可以在 clients_setores 表中创建一个条目。

我想要做的是能够从下拉菜单中选择属于给定 setor_id 的用户并将此关系存储在连接表中。我确实设法使这样的菜单出现在同一个 _form.html.erb 中,并带有以下代码:

<%= f.collection_select :user_ids, User.where(:setor_id => 1), :id, :email %>

但是当我提交表单时,没有保存值。我不知道我的问题是否只是因为我没有正确的方法在我的视图中记录此关联,或者我的问题是否在控制器(可能)和模型(可能)中更进一步。

我在 SO 中发现的最接近的问题是 Rails 4 Accessing Join Table Attributes,但关联类型不同(has_many/through)并且不涉及第三个关系,所以我不知道如何让它为我工作。

【问题讨论】:

  • 嘿,我没有完全理解你的问题,所以如果你能澄清“我的问题是:在这个连接表中我添加了对用户模型的引用”的意思。 has_and_belongs_to_many 仅允许两列(setor 和 client 表的外键),因此如果您说要添加对该表的引用,则必须使用“has_many through”设置。此外,您没有将您的客户属于您的客户模型中的用户。
  • 对于一个拥有多个用户的客户端,它必须通过相同数量的 Setores(1 个 setor:1 个客户端;3 个 setores:3 个客户端),has_many/through 关系是否像这样工作?至于属于User的Client,永远属于Setores一样多的User;这相关吗?
  • 好吧,你是说如果一个客户有一个用户,他也必须有一个 setore?抱歉,我仍然不确定您要做什么,但是如果您需要一种方法来确保客户端和 setores 也同时了解用户,您将需要使用“has_many through”关联,以便您可以向该联接表添加其他列以存储有关用户的额外信息。
  • 没错。在该系统的逻辑顺序中,必须首先为客户分配一个 Setor,然后才能分配一个用户(来自所述 Setor)。 (Setor 的意思是“部门”。如果我的客户需要应付账款部门的服务,它会从这个部门得到一个帮助)

标签: mysql ruby-on-rails ruby


【解决方案1】:

三个模型之间的多对多关联示例,使用单个连接表完成:

我从生成一些模型开始:

rails g model User; rails g model Setor; rails g model Client;
rails g model Joiner user_id:integer setor_id:integer client_id:integer

顺便说一句,references 是一种添加引用现有模型的外键的方法。 IE。 user:references 将创建一个 user_id 列。它还为外键添加了一个“索引”,从而提高了性能。

然后我给类添加一些关联

class Joiner
  # columns: user_id, setor_id, client_id
  belongs_to :user
  belongs_to :setor
  belongs_to :client
end

class User
  has_many :joiners
  has_many :setors, through: :joiners, source: :setor
  has_many :clients, through: :joiners, source: :client
end

class Setor
  has_many :joiners
  has_many :users, through: :joiners, source: :user
  has_many :clients, through: :joiners, source: :client
end

class Client
  has_many :joiners
  has_many :users, through: :joiners, source: :user
  has_many :setors, through: :joiners, source: :setor
end

编写此代码后,您就有了三个模型的多对多关联。

然后你可以写:

User.create; Setor.create;
Joiner.create(user_id: User.first.id, setor_id: Setor.first.id);
User.first.setors.length # => 1

顺便说一句,这不适用于自联接(即嵌套评论系统),但这不是问题的一部分。

【讨论】:

  • 在这种情况下,我将在哪里存储客户和他的(最多三个)UserSetor 配对之间的关​​系?
  • @SamOliver 可能是另一个连接表。 ClientUserSetor 也许。它不漂亮,但它会成功。顺便看看detailed association reference
  • 我读了你的第一个答案几次,它给了我创建一个新模型的想法,比如“WeirdRelation”,一个只存储 user_id、setor_id 和 user_id 的表。这不是我选择解决这个特定问题的方式(请参阅下面的答案),但如果我每个客户有更多的“Setores”,我就会这样做。
  • 好的,如果你有这样一个非常简单的案例,这种方法会起作用,但我猜你这样做的唯一原因是因为你并不真正了解如何将多对-许多关系。查看有关该主题的其他 stackoverflow 问题。
  • @SamOliver 我重新做了我的回答,给你一个更具体的例子。希望清楚。
【解决方案2】:

为了达到预期的效果,我最终做的是向 Client 模型添加三列:

用户组1

用户组2

用户组3

这样,根据客户为他服务的 Setores(部门),客户最多可以与用户建立三个(因为该字段可以是空白)关系。

这是最简单的解决方案在这种情况下,因为我只有 3 个 Setores。它不适用于更大的数字。

如果我有超过 3 个 Setore,那么继续在 Client 表中添加列是不切实际的,我会创建一个新模型来存储关系,在这种情况下,除了唯一 ID 之外,还有一个表, client_id、setor_id 和 user_id。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    相关资源
    最近更新 更多