I am learning Ruby on Rails and am currently struggling to implement a many-to-many relationship.
I have a user and a carpool that can be driven by a user and ridden by multiple users. So, I am trying to implement a join table carpools_users with has_and_belongs_to_many. I assume there is something wrong with my models but I can't figure out what I am doing wrong exactly.
Currently a RuntimeError gets thrown because i am violating a not null constraint of carpools_users.carpool_id .
Migrations
20230621132948_create_carpools.rb
class CreateCarpools < ActiveRecord::Migration[7.0]
def change
create_table :carpools do |t|
t.references :driver, foreign_key: { to_table: 'users' }
t.references :passenger, foreign_key: { to_table: 'users' }
t.timestamps
end
end
end
20230621123159_create_users.rb
class CreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :name
t.references :ridden_carpool, foreign_key: { to_table: 'carpools' }
t.references :driven_carpool, foreign_key: { to_table: 'carpools' }
t.timestamps
end
create_join_table :users, :carpools, :id => false
end
end
Models
carpool.rb
class Carpool < ApplicationRecord
belongs_to :driver, :class_name => 'User', :foreign_key => "driver_id"
has_and_belongs_to_many :passenger, :class_name => 'User', :foreign_key => "user_id"
end
user.rb
class User < ApplicationRecord
has_many :driven_carpools, :class_name => "Carpool", :foreign_key => "driven_carpool_id"
has_and_belongs_to_many :ridden_carpools, :class_name => "Carpool", :foreign_key => "carpool_id"
end
Inside your CreateUser, in this line, the
:id => false, I don't think it is necessary. When you create a join table, the table will have 2 columns with the id of each model you included by default, and that's it. Check here create_join_table and here Create Join TableIn your CreateCarPool, I believe you have many passengers, so
passengershould be in the plural.Also in CarPool, on his line,
passengershould be plural.Maybe in your User model you going to update the foreign_key on the has_many and also add the join table to the has_and_belongs relationship. The foreign_key for your user in CarPool is driver_id, that's the one which you used to associate.
Another thing is. I don't know in which order you creating these tables and updating your models, but you need to follow first with User, basic CarPool,
rails db:migrate, then go for updating your models, always remembering to migrate after changes. For na ID to be used, you first need to migrate before going to next step.