1

Rails 5.

I have been trying to create a self referencing has_many relationship based on this tutorial: https://medium.com/@jbmilgrom/active-record-many-to-many-self-join-table-e0992c27c1e (the last piece: Has_many | Has_many — Self Join Table)

I also see various threads here about this concept but I'm still a little lost when it comes to my problem and its terminology. And I am not sure what the database should look like. I should also mention that I am very new to Rails.

I am trying to create 'representative' - 'represented' relationship between Users.

A User can be represented by many Users (User has_many Representatives). And a User can represent many Users (User has_many Represented).

Based on the tutorial in the link above I wrote my User model like this:

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

Then I created a representatives table like so (I called it representatives but its really the group of representatives and represented):

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

I also created a representatives table in the database which looks like this:

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

So, In the Rails console I create two users:

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

I want u2 to represent u1:

u1.representatives = [u2]

But I get this error:

NameError: uninitialized constant User::representatives

I'm finding this concept quite confusing and the other threads here don't clear it up for me. Can someone break this concept down in relation to my problem?

ThriceGood
  • 1,633
  • 3
  • 25
  • 43
  • Possible duplicate of [Rails: self join scheme with has\_and\_belongs\_to\_many?](https://stackoverflow.com/questions/19770888/rails-self-join-scheme-with-has-and-belongs-to-many) – BookOfGreg Aug 16 '17 at 08:47

2 Answers2

0

Ok so in the end I got it to work with some slight modification. First I renamed some things to make it make a little more sense (if only in my head).

User model:

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

RepresentativeGrouping model:

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

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

One thing that is vital here is the arrangement of the has _many definitions in the User model. In the question about you'll see that the has_many definition with the through: and source: in it was below the has_many definition with the class_name: and foreign_key:. After I had changed the names around I got passed my first error:

NameError: uninitialized constant User::representatives

But moved on to another error:

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

googling led me to here: https://github.com/rails/rails/issues/29123, where someone mentioned the issue with the arrangement of the definitions, and that you must have them in the reverse of my order.

After these changes I was able to run code like this:

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
ThriceGood
  • 1,633
  • 3
  • 25
  • 43
0

In UserModel

To get representatives - has_and_belongs_to_many :representatives, class_name: "User", join_table: : representative_groupings, foreign_key: :represented_id, association_foreign_key: : representative_id

To get 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

Gaudam Thiyagarajan
  • 1,022
  • 9
  • 24