Ruby 在 Rails 上:has_many 自加入

Ruby on Rails: has_many self join

Rails 5.

我一直在尝试根据这个教程创建一个自引用has_many关系:https://medium.com/@jbmilgrom/active-record-many-to-many-self-join-table-e0992c27c1e(最后一块:Has_many | Has_many — Self Join Table)

我在这里也看到了关于这个概念的各种线索,但当涉及到我的问题及其术语时,我仍然有点迷茫。而且我不确定数据库应该是什么样子。我还应该提到我是 Rails.

的新手

我正在尝试在用户之间创建 'representative' - 'represented' 关系。

一个用户可以由多个用户代表(用户has_many代表)。 而一个User可以代表很多User(User has_many Represented).

根据上面link中的教程,我这样写了我的用户模型:

class User < ApplicationRecord
  has_many :representatives, through: :representive_link, source: :representative
  has_many :representive_link, foreign_key: :represented_user_id, class_name: 'representatives'

  has_many :represented, through: :represented_link, source: :represented
  has_many :represented_link, foreign_key: :representative_user_id, class_name: 'representatives'
end

然后我像这样创建了一个代表table(我称它为代表,但它实际上是一组代表和代表):

class Representatives < ActiveRecord::Base
  belongs_to :representative, foreign_key: 'representative_user_id', class_name: 'User'
  belongs_to :represented, foreign_key: 'represented_user_id', class_name: 'User'
end

我还在数据库中创建了一个代表 table,如下所示:

+----------------------+------------+------+-----+---------+----------------+
| Field                | Type       | Null | Key | Default | Extra          |
+----------------------+------------+------+-----+---------+----------------+
| id                   | bigint(20) | NO   | PRI | NULL    | auto_increment |
| representive_user_id | bigint(20) | YES  | MUL | NULL    |                |
| represented_user_id  | bigint(20) | YES  | MUL | NULL    |                |
| created_at           | datetime   | NO   |     | NULL    |                |
| updated_at           | datetime   | NO   |     | NULL    |                |
+----------------------+------------+------+-----+---------+----------------+

因此,在 Rails 控制台中我创建了两个用户:

u1 = User.create('id' => 1, 'username' => 'john')
u2 = User.create('id' => 2, 'username' => 'mike')

我想让u2代表u1:

u1.representatives = [u2]

但是我得到这个错误:

NameError: uninitialized constant User::representatives

我发现这个概念很混乱,这里的其他主题并没有为我澄清。有人可以根据我的问题分解这个概念吗?

好的,最后我稍微修改了一下就可以使用了。首先,我重命名了一些东西以使其更有意义(如果只是在我的脑海中)。

用户模型:

class User < ApplicationRecord
  has_many :represented_link, foreign_key: :representative_id, class_name: 'RepresentativeGrouping'
  has_many :represented, through: :represented_link, source: :represented

  has_many :representive_link, foreign_key: :represented_id, class_name: 'RepresentativeGrouping'
  has_many :representatives, through: :representive_link, source: :representative
end

代表分组模型:

class RepresentativeGrouping < ApplicationRecord
  belongs_to :representative, foreign_key: 'representative_id', class_name: 'User'
  belongs_to :represented, foreign_key: 'represented_id', class_name: 'User'
end

representative_grouping table:

mysql> describe representative_groupings;
+-------------------+------------+------+-----+---------+----------------+
| Field             | Type       | Null | Key | Default | Extra          |
+-------------------+------------+------+-----+---------+----------------+
| id                | bigint(20) | NO   | PRI | NULL    | auto_increment |
| representative_id | bigint(20) | YES  | MUL | NULL    |                |
| represented_id    | bigint(20) | YES  | MUL | NULL    |                |
| created_at        | datetime   | NO   |     | NULL    |                |
| updated_at        | datetime   | NO   |     | NULL    |                |
+-------------------+------------+------+-----+---------+----------------+

这里至关重要的一件事是用户模型中 has _many 定义的排列。在关于您的问题中,您会看到带有 through: 和 source: 的 has_many 定义低于带有 class_name: 和 foreign_key: 的 has_many 定义。在我更改了周围的名称后,我通过了第一个错误:

NameError: uninitialized constant User::representatives

但转到另一个错误:

ActiveRecord::HasManyThroughOrderError: Cannot have a has_many :through association 'User#representatives' which goes through 'User#representive_link' before the through association is defined.

谷歌搜索把我带到了这里:https://github.com/rails/rails/issues/29123,有人提到了定义排列的问题,你必须按照我的顺序相反。

进行这些更改后,我可以 运行 编写如下代码:

u1 = User.create(:id => 1, :username => 'john')
u2 = User.create(:id => 2, :username => 'mike')

u1.representatives = [u2]
puts u1.representatives

### displays u2's data

puts u2.represented

### displays u1's data

在用户模型中

获得代表 - has_and_belongs_to_many :representatives, class_name: "User", join_table: : representative_groupings, foreign_key: :represented_id, association_foreign_key: : representative_id

得到represented_by- has_and_belongs_to_many : represented, class_name: "User", join_table: : representative_groupings, foreign_key: :representative_id, association_foreign_key: : represented_id

This also eliminates the need for your explicit model rails - RepresentativeGrouping