DEV Community

Sid Saythongphet
Sid Saythongphet

Posted on

Phase 4 project

Working on my phase 4 project for the Flatiron School has really opened up my eyes to the complexity of creating a fullstack application. From designing the front end with React.js, to creating an API using Ruby on Rails and integrating the use of Amazon Web Service S3, I was pleasantly surprised to see how it all worked together. And I know I have only touched the surface of it all with it all still being new to me.

One of the things I had to spend some time on for this project was the associations. I had worked with the one-to-many and many-to-many relationships between multiple tables before in my previous project, but this time around, I found myself needing to implement a relationship between a table and its self.

For this project I had a User table which, each user was able to follow another user. In accomplishing this relationship, I approached it by creating a join table for the relationship, which I named Followship.

rails g resource Followship follower_id:integer followee_id:integer

In creating this table, I added the attributes follower_id, indicating the user that was doing the following, and followee_id, indicating the user that was being followed. Then before migrating this table to my database, I added indexes for each of the attributes, as well as making a specific follower_id, followee_id combinating index unique to prevent duplicate followship relationships. My migration ended up looking like this:

class CreateFollowships < ActiveRecord::Migration[7.0]
  def change
    create_table :followships do |t|
      t.integer :follower_id
      t.integer :followee_id

    add_index :followships, :follower_id
    add_index :followships, :followee_id
    add_index :followships, [:follower_id, :followee_id], unique: true
Enter fullscreen mode Exit fullscreen mode

After migrating, I moved to my Followship model.

class Followship < ApplicationRecord
  belongs_to :follower, foreign_key: 'follower_id', class_name: 'User'
  belongs_to :followee, foreign_key: 'followee_id', class_name: 'User'

  validates :follower_id, presence: true
  validates :followee_id, presence: true
Enter fullscreen mode Exit fullscreen mode

Here, I indicated the two belongs_to associations since this was a joins table. Unlike joining a table to another table, I had to add a couple of other options. Because :follower and :followee are not models in themselves, I had to include a class_name attribute that indicated what table to look push from, in this case the User table. I need assigned which column in my followship table it cooresponded with.

Once that was set up, I had to move on to my user model to incorporate the has many relationships.

class User < ApplicationRecord

  has_many :followships, dependent: :destroy

  has_many :passive_followships, foreign_key: :followee_id, class_name: 'Followship', dependent: :destroy
  has_many :followers, through: :passive_followships

  has_many :active_followships, foreign_key: :follower_id, class_name: 'Followship', dependent: :destroy
  has_many :followees, through: :active_followships

Enter fullscreen mode Exit fullscreen mode

In setting up my associations in the User model, I created the connection between the two tables. I then created two seperate associations, one indicating the current users followers (:passive_followship) and the other indicating the users the current user is following (:active_followship). Similar to the Followship model, I used the class_name to specify the Followship table and also specifying the foreign_key. I was then able to make a direct relationship between the user and their followers with has_many :followers, through: :passive_followships and a direct relationship between the user and who they follow with has_many :followees, through: :active_followships.


This process did take me some time to wrap my head around, but I enjoyed the journey. Working through the project for the last couple of weeks has had its ups and downs, but I feel accomplished with the work I have been able to do thus far!

Top comments (0)