DEV Community

Kyle Trahan
Kyle Trahan

Posted on

Self-Referential m:n Relationships

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
Enter fullscreen mode Exit fullscreen mode

And of course my users table (slimmed down for readability).

create_table "users", force: :cascade do |t|
    t.string "username"
  end
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
class Partnership < ApplicationRecord
belongs_to :requestor, class_name: :User
    belongs_to :receiver, class_name: :User
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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!

Top comments (0)