繁体   English   中英

如何使用同一Rails模型中的两个记录作为不同Rails模型中的外键?

[英]How can I use two records from the same Rails model as foreign keys in a different Rails model?

我有两个模型:person.rb和Relationship.rb

我需要我的:relationships表来引用:people表中的两行作为外键。

这是两个表的迁移:

class CreatePeople < ActiveRecord::Migration[5.1]
  def change
    create_table :people do |t|
      t.string :first_name
      t.string :second_name
      t.integer :age
      t.string :gender
      t.timestamps
    end
  end
end

class CreateRelationships < ActiveRecord::Migration[5.1]
  def change
    create_table :relationships do |t|
      t.references :person_a
      t.references :person_b
      t.string :status
      t.timestamps
    end
  end
end

这个想法是::person_a和:person_b字段都是来自:people表的单独记录(被引用为外键),而:status字段仅是它们之间关系的描述(“已婚”,“朋友”,“分离”等)

我试图找出:

1)为了将:person_a和:person_b设置为来自:people表的外键,我必须在上面的CreateRelationships迁移中编写额外的代码?

2)我需要在下面的两个表的模型文件(person.rb和Relationship.rb)中编写什么代码来定义我正在谈论的关系结构?

class Person < ApplicationRecord
end

class Relationship < ApplicationRecord
end

我在这里发现了另一个问题可以解决这个问题,但是给出的答案是矛盾的,有些不完整,还有其他使用旧版本的Rails的问题。 他们都没有为我工作。

我正在使用Rails 5.1.4

您已经正确定义了迁移,只需在模型中添加以下内容即可定义模型之间的关系。

    class Person < ApplicationRecord::Base
      has_many :relationships, dependent: :destroy
    end

    class Relationship < ApplicationRecord::Base
      belongs_to :person_a, :class_name => 'Person'
      belongs_to :person_b, :class_name => 'Person'
    end

这样,您可以像下面这样访问一个关系所属的人:

@relationship.person_a #user assigned as the first person.
@relationship.person_b #user assigned as the second person.

希望这行得通。

对于聊天模块,我必须执行相同的操作,这是如何执行此操作的示例:

class Conversations < ApplicationRecord
  belongs_to :sender, foreign_key: :sender_id, class_name: 'User'
  belongs_to :recipient, foreign_key: :recipient_id, class_name: 'User'
end

class User < ApplicationRecord
  ...
  has_many :conversations
  has_many :senders, through: :conversations, dependent: :destroy
  has_many :recipients, through: :conversations, dependent: :destroy
  ...
end

更多的解释, 有很多

希望能帮助到你,

编辑:道歉的匆忙和错误的答案。

最初,我认为简单的has_many/belongs_to关联是可能且足够的。

class Person < ApplicationRecord
  has_many :relationships #dependent: :destroy
end

class Relationship < ApplicationRecord
  belongs_to :person_a, class_name: "Person"
  belongs_to :person_b, class_name: "Person"

  enum status: [:married, :friends, :separated]
end

正如@engineersmnky所指出的, has_many关联在这里不能工作,因为relationships表中没有person_id列。 由于我们只能在has_many关联中声明一个自定义外键,因此无法以这种方式声明它。 belongs_to可以工作,但我认为这还不够。

一种方法是跳过声明has_many并坚持使用自定义方法来查询关系:

class Person < ApplicationRecord
  def relationships
    Relationship.where("person_a_id = ? OR person_b_id = ?", id, id)
  end
end

它将为您提供一个ActiveRecord::Relation来使用,其中包含所需的确切记录。 该解决方案的缺点很多-根据您的需求,您可能需要更多的代码来插入数据,首先需要使用setter方法将关系分配给人们...

真正的解决方案是在Relationship模型中有一个复合主键,该主键由:person_a_id:person_b_id ActiveRecord不支持复合主键,但是这个宝珠似乎可以填补空白。 显然,它允许声明这样的密钥并将其用作has_many关联中的外键。 要注意的是,您的person_a / person_b对在relationships表中必须是唯一的。

您可以像这样在关系模型中编写

belongs_to : xyz, class_name: "Person", foreign_key: "person_a"
belongs_to : abc, class_name: "Person", foreign_key: "person_b"

亲自模型

has_many :relationships, dependent: :destroy

希望对你有帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM