Self-Referential m:n Relationships
Kyle Trahan
Posted on October 6, 2020
The Journey to Having Friends
I recently finished up my mod3 project called Belay Land. One of the key aspects of this project was learning how to create a backend that would allow my users to form belay partnerships with other users. After doing some research I came across self-referential m:n relationships and it was exactly what I needed.
Creating Your Tables
The first step was to migrate the two tables that would be used to make the relationship.
Partnerships is my join table. I added in a partnership status column and set the default to pending in order to keep track of the partnership being accepted by the receiving party.
create_table "partnerships", force: :cascade do |t|
t.integer "requestor_id"
t.integer "receiver_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "partnership_status", default: "pending"
end
And of course my users table (slimmed down for readability).
create_table "users", force: :cascade do |t|
t.string "username"
end
Setting Up the Model Relationships
The next step was to set up the relationships between my models. I created a User and Partnership model. Giving them the follow relationship I was able to make a connection between users.
class User < ApplicationRecord
has_many :partnerships_as_requestor, foreign_key: :requestor_id, class_name: :Partnership
has_many :partnerships_as_receiver, foreign_key: :receiver_id, class_name: :Partnership
class Partnership < ApplicationRecord
belongs_to :requestor, class_name: :User
belongs_to :receiver, class_name: :User
This relationship essentially creates subclasses of the User class in order to allow users to be a receiver or a requestor of a partnership request.
Showing Your Partnerships
I added a serializer to my User model in order to have access to these partnerships being created.
class UserSerializer
includes FastJsonapi:ObjectSerializer
attributes :partnerships_as_requestor, :partnerships_as_receiver
This is about as far as I took my backend in order to create the relationship. The rest of it was taken care of with Javascript on the frontend.
Challenges
Overall my biggest challenge was not developing my backend enough. I found myself having to dig through my data a bit more on the frontend than I would of liked to in order to access the partnerships. I would definitely recommend writing yourself a few methods in your backend to fix this. One suggestion I would do is to create a method to make a list of all of your partnerships with the status of accepted.
I hope this is helpful for someone trying to create a self-referential m:n relationship, goodluck!
Posted on October 6, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.