Ignacio Martínez
Ignacio Martínez

Reputation: 702

Self has_and_belongs_to_many relationhip

I'm trying to create self join using has_and_belongs_to_many.

I have a User model which would associate with itself. A User can be a teacher and a student at the same time. So a User can be a teacher of another User who is a student.

I did this:

class User < ActiveRecord::Base    
has_and_belongs_to_many :teachers, 
    class_name: "User", 
    join_table: :students_teachers, 
    foreign_key: "user_id",
    association_foreign_key: :teacher_id
  has_and_belongs_to_many :students,
    class_name: "User", 
    join_table: :students_teachers,
    foreign_key: "user_id",
    association_foreign_key: :student_id

But when I try to add a teacher to a User's teacher list I get this:

User.first.teachers << User.last
ActiveRecord::UnknownAttributeError: unknown attribute 'user_id' for User::HABTM_Teachers.

What am I missing?

UPDATE

I found out that I was doing something else wrong and made some changes, buy now have a different error that still don't know how to solve.

I created two different relation tables so there's users_teachers and users_students.

    has_and_belongs_to_many :teachers, 
    class_name: "User",
    join_table: :users_teachers, 
    foreign_key: "id",
    association_foreign_key: :teacher_id
  has_and_belongs_to_many :students, 
    class_name: "User",
    join_table: :users_students,
    foreign_key: "id",
    association_foreign_key: :student_id

Now I'm able to add a teacher to a user, or a student to a user. The thing is that I can't add more than one because user_id is primary and I don't know how to change that on the relation table. Here is the schema code:

    create_table "users_students", force: :cascade do |t|
    t.integer "user_id"
    t.integer "student_id"
  end

  add_index "users_students", ["student_id"], name: "index_users_students_on_student_id", using: :btree
  add_index "users_students", ["user_id"], name: "index_users_students_on_user_id", using: :btree

  create_table "users_teachers", force: :cascade do |t|
    t.integer "user_id"
    t.integer "teacher_id"
  end

    add_index "users_teachers", ["teacher_id"], name: "index_users_teachers_on_teacher_id", using: :btree
      add_index "users_teachers", ["user_id"], name: "index_users_teachers_on_user_id", using: :btree

On my second attempt to add a teacher or student I get:

ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "users_teachers_pkey"
DETAIL:  Key (id)=(1) already exists.

Upvotes: 0

Views: 319

Answers (1)

Ignacio Mart&#237;nez
Ignacio Mart&#237;nez

Reputation: 702

I found my mistake. Instead of foreign_key: "id" I had to put foreign_key: "user_id"

Upvotes: 1

Related Questions