Ruby on Rails:has_many自我加入

时间:2017-08-16 08:07:31

标签: ruby rails-activerecord ruby-on-rails-5 has-many-through has-many

Rails 5。

我一直在尝试根据本教程创建一个自引用has_many关系:https://medium.com/@jbmilgrom/active-record-many-to-many-self-join-table-e0992c27c1e(最后一篇:Has_many | Has_many - 自我加入表)

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

我正试图在用户之间建立'代表' - '代表'的关系。

用户可以由许多用户(用户has_many代表)代表。 并且用户可以代表许多用户(用户has_many代表)。

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

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

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

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

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

+----------------------+------------+------+-----+---------+----------------+
| 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

我发现这个概念很混乱,而这里的其他线程并没有为我清除它。有人可以根据我的问题打破这个概念吗?

2 个答案:

答案 0 :(得分:0)

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

用户模型:

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表:

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    |                |
+-------------------+------------+------+-----+---------+----------------+

这里至关重要的一点是在用户模型中安排了_many定义。在关于你的问题中你会看到带有through:和source:的has_many定义在它下面的has_many定义下面是class_name:和foreign_key:。在我改变了名字后,我得到了第一个错误:

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

答案 1 :(得分:0)

在UserModel中

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

获取 represent_by - has_and_belongs_to_many : represented, class_name: "User", join_table: : representative_groupings, foreign_key: :representative_id, association_foreign_key: : represented_id

  

这也消除了对显式模型 rails 的需求 -    RepresentativeGrouping