Follow function association memorandum (understand the description of the User model)

table of contents

-Introduction

-[Create an intermediate table because it is many-to-many](#Create an intermediate table because it is many-to-many)

-[Think model in two (important here)](# Think model in two here important)

-[(1) Think from the perspective of the follower](#Think from the perspective of the follower)

-[② Think from the perspective of the follower](#Think from the perspective of the follower)

-Summary

Introduction

For the past few days, I've had a hard time understanding the follow function association, but I've finally managed to put it into myself, so I'll leave it as a memorandum.

Personally, I got confused at the ** description of the association to the User model **, so I mainly write about it. So this time, I haven't touched on the implementation of view and controller.

So I will start immediately.

Create an intermediate table because it is many-to-many

Because the follow function association is a many-to-many (user-to-user) association, It is necessary to prepare an intermediate table and make it a "one-to-many" (user-to-relationships) association.

(For those who like one-to-many or many-to-many, [[for beginners] Rails "association" tutorial that is too polite [anything] [perfectly understood]](https://qiita.com/kazukimatsumoto/items/14bdff681ec5ddac26d1 #% E3% 83% 95% E3% 82% A9% E3% 83% AD% E3% 83% BC% E3% 83% 95% E3% 82% A9% E3% 83% AD% E3% 83% AF% E3% 83% BC% E6% A9% 9F% E8% 83% BD% E3% 82% 92er% E5% 9B% B3% E3% 82% 92% E4% BD% BF% E3% 81% A3% E3% 81% A6% E8% A8% AD% E8% A8% 88% E3% 81% 97% E3% 82% 88% E3% 81% 86) I recommend this article too. I learned.)

So, first create a relationship model.

$ rails g model Relationship

Add following_id (following side id) and follower_id (following side id) etc. to the migration file.

202008111333110_create_relationships.rb


class CreateRelationships < ActiveRecord::Migration[5.2]
  def change
    create_table :relationships do |t|
      #Follower
      t.integer :following_id
      #Followed side
      t.integer :follower_id

      t.timestamps null: false
    end
    add_index :relationships, :following_id
    add_index :relationships, :follower_id    
    add_index :relationships, [:following_id, :follower_id], unique: true
  end
end

Don't forget ...

$ rails db:migrate

Divide the model into two parts (important here)

From here ** ① Looking at the follower ** ** ② Looking at the side to be followed ** It is necessary to distinguish between the two. Be careful as you will not know what it is if you make it ambiguous!

First of all ... ** 1. Think of the Relationship model in two parts ** ・ Active_relationships (following side's eyes) ・ Passive_relationships (eyes of the follower)

user.rb


class User < ApplicationRecord
  has_many :active_relationships, class_name: "Relationship", foreign_key: :following_id, dependent: :destroy
  has_many :passive_relationships, class_name: "Relationship", foreign_key: :follower_id, dependent: :destroy
end

Since it is just an "assuming" that one Relationship model is given a name and divided into two models, it is necessary to describe in class_name that it is really a Relationship model.

Also, from the perspective of the follower, the follower (follower_id) is pulled based on the follower (following_id), so it is necessary to specify the primary_key (foreign key) as the following_id.

On the contrary, from the perspective of the follower, the follower (following_id) is pulled based on the follower (follower_id), so it is necessary to specify the primary_key (foreign key) as the follower_id.

** 2. Think of the User model in two parts ** ・ Following (Looking at the side to follow) ・ Follower (the line of sight of the follower)

relationship.rb


class Relationship < ApplicationRecord
  belongs_to :following, class_name: "User"
  belongs_to :follower, class_name: "User"
end

As with the Relationship model, it is just an "assuming" that one User model is given a name and divided into two models, so it is necessary to describe in class_name that it is really a User model.

① Think from the perspective of the follower

1st line: ** Describe the Relationships model (active_relationships because it is the side to follow here) ** It has already been explained where the above Relationships model is divided into two.

Line 2: ** Gather people followed via active_relationship ** Gather people followed through active_relationships. To collect the people who are followed, you will refer to the "follower" model, so write source :: follower. Since this series of flow is named "followings", it is described as has_many: followings.

user.rb


  has_many :active_relationships, class_name: "Relationship", foreign_key: :following_id
  has_many :followings, through: :active_relationships, source: :follower

② Think from the perspective of the person being followed

Line 1: ** First, describe the Relationships model (passive_relationships here) ** It has already been explained where the above Relationships model is divided into two.

2nd line: ** Gather people you follow via passive_relationship ** Gather people who are followed through passive_relationships. To collect the people who are followed, you will refer to the "following" model, so write source :: following. Since this series of flow is named "followers", it is described as has_many: followers.

user.rb


  has_many :passive_relationships, class_name: "Relationship", foreign_key: :follower_id
  has_many :followers, through: :passive_relationships, source: :following

So the final description in the User model is as follows.

user.rb


class User < ApplicationRecord
  #The line of sight of the follower
  has_many :active_relationships, class_name: "Relationship", foreign_key: :following_id
  has_many :followings, through: :active_relationships, source: :follower

  #Looking at the side to be followed
  has_many :passive_relationships, class_name: "Relationship", foreign_key: :follower_id
  has_many :followers, through: :passive_relationships, source: :following
end

This is the end.

Summary

In order to complete the follow function, it is necessary to implement view and controller separately.

That said, I actually experienced and felt that the mountain of follow function implementation lies in "understanding the description of the User model", so I think that if you cross this mountain, you can implement it without difficulty. : thumbsup:

I think the point this time is ** to think about one model in two **.

In the first place, the structure that both the follower and the follower refer to one model called the User model and bring the data is complicated, so it seems to be the relationship between the Post model of the like function and the User model. In addition, if you assume that the User model is two models (although it is actually one model) and organize the relationships, I think that you can think that it may be an unexpectedly simple story.

Thank you for reading this far. I'm a beginner who doesn't have enough knowledge yet, so I would appreciate it if you could give me some advice if there are any mistakes.

Recommended Posts

Follow function association memorandum (understand the description of the User model)
Let's understand the function!
About the description of Docker-compose.yml
Understand the basics of docker
Problem that the attribute of User model becomes nil in ActionMailer
Understand the basic mechanism of log4j2.xml
User evaluation using the like function
[Rails] Implementation of user withdrawal function
A memorandum of the FizzBuzz problem
[Rails] I will explain the implementation procedure of the follow function using form_with.
How to implement the email authentication function at the time of user registration
Understand the basics of Android Audio Record
Implementation of user authentication function using devise (2)
Understand the official sample Coffee of Dagger2
Implementation of user authentication function using devise (1)
Where the follow function implementation is stuck
Implementation of user authentication function using devise (3)