[RUBY] [Rails] Je vais expliquer la procédure d'implémentation de la fonction follow en utilisant form_with.

Aperçu

J'écrirai la procédure pour implémenter la fonction suivante en utilisant form_with!

Nous implémenterons les fonctions suivantes __1. Possibilité de suivre / ne plus suivre les utilisateurs __ __2. Suivez la fonction d'affichage de la liste des utilisateurs / abonnés __

Je me suis référé à l'article Comment faire une fonction de suivi avec Rails, et surtout pour une explication détaillée de l'association liée à la fonction de suivi, cet article est très utile. devenu!

supposition

environnement ・ Rails 5.2.4.2 ・ Rubis 2.6.5 · Svelte · Concevoir

__ De plus, on suppose que les fonctions utilisateur sont implémentées. __

__ Comment configurer une application Rails dans l'environnement ci-dessus __

__ ↓ Cela ressemblera à ceci après la mise en œuvre. (Je suis désolé, ça a l'air simple ...) ↓ __ ezgif.com-video-to-gif (3).gif

Implémentation de la fonction follow / unfollow

1. Création de modèles de relations

$ rails g model Relationship user:references follow:references

__ · La table des relations créée ici est une table intermédiaire pour les utilisateurs à suivre et les utilisateurs à suivre. __

La table intermédiaire reconnaît __ ・ ʻusercomme modèle d'utilisateur suiveur etfollow` comme modèle d'utilisateur suiveur. __


2. Modifier le fichier de migration des relations

db/migrate/[timestamps]_create_relationships.rb


class CreateRelationships < ActiveRecord::Migration[5.2]
  def change
    create_table :relationships do |t|
      t.references :user, foreign_key: true
      t.references :follow, foreign_key: { to_table: :users }
 
      t.timestamps
 
      t.index [:user_id, :follow_id], unique: true
    end
  end
end

La raison pour laquelle les modèles référencés sont séparés par __ · utilisateur et suit est que «l'utilisateur suivant» et «l'utilisateur suivi» doivent être considérés comme des modèles séparés. __

__ · t.references: user, Foreign_key: true__: __user La clé externe du modèle est définie. __

__ · t.references: follow, clé_tranger: {to_table :: users} __: __follow La clé externe du modèle est définie. Le modèle suivant est un nom de modèle fictif qui n'existe pas, et je le crée en ce moment. Par conséquent, en définissant {to_table :: users}, le modèle de la source de référence est enseigné. __

__ ・ t.index [: user_id ,: follow_id], unique: true__: En donnant l'unicité à la combinaison de __user_id et follow_id, la duplication des données est empêchée, c'est-à-dire que le même utilisateur est suivi deux fois. Est prévenu. __


3. Enregistrez le contenu de DB

$ rails db:migrate

4. Décrivez l'association pour l'utilisateur dans le modèle de relation.

app/models/relationship.rb


class Relationship < ApplicationRecord
  belongs_to :user
  belongs_to :follow, class_name: "User"
 
  validates :user_id, presence: true
  validates :follow_id, presence: true
end

__ · appartient_à: utilisateur__: __ C'est l'association habituelle. __

__ · appartient à: follow, nom_classe:" User " __: __ Il est décrit qu'il appartient à la classe suivante, mais comme mentionné ci-dessus, follow est une classe fictive, alors faites-y référence par nom_classe:" Utilisateur " Je vais vous dire le modèle d'origine. __


5. Décrivez l'association pour la relation dans le fichier de modèle utilisateur.

app/models/user.rb


class User < ApplicationRecord
 
#==============Association avec les utilisateurs suivis par un utilisateur=================
  has_many :relationships, foreign_key: "user_id",
                           dependent: :destroy
  has_many :followings, through: :relationships, source: :follow
#==========================================================================
 
#==============Association avec des utilisateurs qui suivent un utilisateur================
  has_many :passive_relationships, class_name: "Relationship",
                                   foreign_key: "follow_id",
                                   dependent: :destroy
  has_many :followers, through: :passive_relationships, source: :user
#===========================================================================
end

__ · Le fichier de modèle de relation ci-dessus décrit les «associations permettant à un utilisateur d'accéder à un utilisateur suivi» et les «associations permettant à un utilisateur d'accéder à un utilisateur suivi». En d'autres termes, les détails seront décrits plus loin sur la figure. __

Parlons d'abord de l'association avec l'utilisateur qu'un utilisateur suit!

__ · has_many: relations, Foreign_key:" user_id ", depend :: destroy__: __ Ceci déclare une association` qui permet à un utilisateur d'accéder à la clé externe user_id des relations de table intermédiaires. Je suis. __

__ Je pense que c'est facile à comprendre si vous l'imaginez comme suit! __

![Capture d'écran 2020-06-27 13.44.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606750/8a356efb-abfc-dbfa-60ce -9aca47c5c2d3.png)

__ · has_many: followings, through :: relations, source :: follow__: __ Ceci déclare une association qui permet à un utilisateur d'accéder au modèle suivant via le follow_id dans les relations de table intermédiaires. Je vais. __

__ L'image ressemble à ceci! __

![Capture d'écran 2020-06-27 13.57.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606750/1dc2397f-2f50-7056-5dde -32cda530340c.png)

__ ・ Avec les deux lignes ci-dessus, vous pouvez obtenir les utilisateurs que l'utilisateur suit en définissant ʻUser.followings`. Une fois que cela est disponible, vous pouvez facilement afficher une liste d'abonnés d'un certain utilisateur. __

5-2 Ensuite est l'explication de l'association avec l'utilisateur qui suit un certain utilisateur!

__ · has_many: passives_relationships, class_name:" Relationship ", Foreign_key:" follow_id ", depend :: destroy__: __ Ceci déclare une association qui permet à un utilisateur d'accéder au follow_id de passives_relationships. Je suis. Puisque passive_relationships est un modèle fictif que j'ai créé moi-même, j'enseigne le modèle référent en tant que nom_classe: "Relation". __

L'image est la suivante!

![Capture d'écran 2020-06-27 14.13.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606750/56cc736f-ccb5-6e43-3202 -1e57d223520a.png)

__ · has_many: followers, through :: passive_relationships, source :: user__: __ Ceci déclare une association qui permet à un utilisateur d'accéder à des followers via le user_id de passive_relationships. __

L'image est la suivante!

![Capture d'écran 2020-06-27 14.26.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606750/6258ee85-2d12-5a92-66a2 -3f5281d57f3b.png)

__ ・ À partir des deux lignes ci-dessus, si vous utilisez User.followers, vous pouvez obtenir les utilisateurs qui suivent User. Avec cela, vous pouvez facilement afficher une liste d'utilisateurs qui suivent un certain utilisateur! __


6. Définissez les méthodes d'instance liées au suivi dans le fichier de modèle utilisateur

app/models/user.rb


class User < ApplicationRecord
  .
  .
  .
  #<Description relative à l'association omise>
  .
  .
  .
  def following?(other_user)
    self.followings.include?(other_user)
  end

  def follow(other_user)
    unless self == other_user
      self.relationships.find_or_create_by(follow_id: other_user.id)
    end
  end

  def unfollow(other_user)
    relationship = self.relationships.find_by(follow_id: other_user.id)
    relationship.destroy if relationship
  end
end

-Vérifiez si l'utilisateur suit @user en définissant following? (Other_user) : __ʻUser.followings.include? (@User)`. Lors de la mise en œuvre du bouton de suivi, il est utilisé pour choisir de manière conditionnelle d'afficher le bouton à suivre ou le bouton de ne plus suivre. __

-En définissant follow (autre_utilisateur) : __ʻUser.follow (@user), vous pouvez suivre @user. ʻSauf self == other_user pour vous empêcher de vous suivre. J'utilise find_or_create_by pour faire référence à l'enregistrement d'identifiant de @user s'il existe, et le créer s'il n'existe pas. __

-En définissant __ʻunfollow (autre_utilisateur) __: __ ʻUser.unfollow (@user), vous pouvez ne plus suivre @user. __

-Maintenant que nous avons défini la méthode à suivre et ne plus suivre __user, l'étape suivante consiste à créer un contrôleur de relations et à implémenter la fonction pour accéder réellement à la base de données et suivre / ne plus suivre en utilisant ces méthodes. Je le ferai! __


7. Créez un contrôleur de relations.

$ rails g controller relationships 

app/controllers/relationships_controller.rb


class RelationshipsController < ApplicationController

  before_action :set_user

  def create
    following = current_user.follow(@user)
    if following.save
      flash[:success] = "Suivi de l'utilisateur"
      redirect_to @user
    else
      flash.now[:alert] = "Impossible de suivre l'utilisateur"
      redirect_to @user
    end
  end

  def destroy
    following = current_user.unfollow(@user)
    if following.destroy
      flash[:success] = "Utilisateur non suivi"
      redirect_to @user
    else
      flash.now[:alert] = "Impossible de se désabonner de l'utilisateur"
      redirect_to @user
    end
  end

  private
  def set_user
    @user = User.find(params[:relationship][:follow_id])
  end
end

-Dans le contrôleur __relationships, seule l'action de création qui suit l'utilisateur et l'action de destruction qui se désactive fonctionnent, donc n'écrivez que l'action de création et l'action de destruction. __    -Depuis le formulaire du bouton __` suivre / ne plus suivre, les données sont envoyées sous forme de paramètres [: relation] [: id_suivi], donc les données sont sous la forme de recherche (params [: relations] [: id_suivi]). Recevoir. __

-__ before_action: set_user__: __ Puisque @user est toujours acquis dans chaque action, après avoir défini la méthode privée set_user, il est acquis à l'avance en utilisant before_action. __

-__ create action __: __ L'utilisateur connecté (current_user) suit le @user acquis. J'utilise la méthode d'instance follow (other_user) définie dans le fichier de modèle utilisateur. __

· __destroy action __: __ L'utilisateur connecté ne suit pas l'utilisateur acquis. J'utilise la méthode d'instance unfollow (other_user) définie dans le fichier de modèle utilisateur. __

・ __ La fonction pour accéder réellement à la base de données et suivre / ne plus suivre est terminée, nous allons donc implémenter le bouton `pour suivre / ne plus suivre '! __


8. Implémentez le bouton suivre / ne plus suivre avec form_with.

__ ・ Commencez par créer un fichier relations / _follow_form.html.slim sous le répertoire app / views. __

ruby:app/views/relationships/_follow_form.html.slim


- unless current_user == user
  #Bouton de désinscription
  - if current_user.following?(user)
    = form_with model: @relationship, url: relationship_path, method: :delete, local: true do |f|
      = f.hidden_field :follow_id, value: user.id
      = f.submit "Se désabonner"
  #Bouton Suivre
  - else
    = form_with model: @set_relationship, url: relationships_path, local: true do |f|
      = f.hidden_field :follow_id, value: user.id
      = f.submit "Suivre"

__ · -à moins que l'utilisateur_actuel == utilisateur__: __ L'affichage du bouton lui-même est commuté de sorte que vous ne pouvez pas vous suivre. L'utilisateur se réfère ici à @user que la vue qui place ce partiel obtient. __

8-1. Explication du bouton de désabonnement

__ · -if current_user.following? (User) __: __ Vérifier si l'utilisateur connecté suit l'autre utilisateur. Si vous suivez, le bouton Ne plus suivre s'affiche et si vous ne le suivez pas, le bouton Suivre s'affiche. __

= form_with model: @relationship, url: relationship_path, method: :delete, local: true do |f|Ceci est un bouton pour se désabonner.

__model: @ relation @relationship est une variable d'instance qui obtient la relation entre l'utilisateur connecté et l'autre utilisateur. __ __ (Si vous placez ce formulaire de bouton de suivi dans app / views / users / show.html.slim, vous définirez la variable d'instance @relationship dans l'action show du fichier app / controllers / users_controller.rb.) __

__ʻUrl: chemin_relation` est le routage vers l'action de destruction du contrôleur de relations. Nous décrirons le routage plus tard. __

__method :: delete spécifie la méthode DELETE dans la requête HTTP. __

Si __local: true n'est pas ajouté, la spécification de soumission du formulaire sera Ajax et les données ne pourront pas être soumises, alors assurez-vous de la décrire dans form_with. __

__ ・ f.hidden_field: follow_id, value: user.id__: Cette partie est facile à comprendre lorsque vous regardez réellement le code source terminé. __

![Capture d'écran 2020-06-27 15.28.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606750/6530abc7-b410-92c6-4f74 -3610f308bc01.png)

En spécifiant> __: follow_id, les données seront envoyées sous la forme de paramètres [: relation] [: follow_id]. La partie définie par la méthode privée set_user du contrôleur de relations reçoit ces données. __

En spécifiant> __valeur: user.id, l'id de l'autre utilisateur qui suit est stocké dans: follow_id et les données sont envoyées. __

8-2. Bouton Suivre

= form_with model: @set_relationship, url: relationships_path, local: true do |f|Ceci est un formulaire pour suivre l'autre utilisateur.

La variable d'instance @set_relationship de model: @ set_relationship génère un modèle vide, et les données sont envoyées sous la forme de paramètres [: relation] [: follow_id] en référence à ce modèle vide. Faire cela.

__ʻUrl: relations_path` est le routage vers l'action de création du contrôleur de relations. Nous décrirons le routage plus tard. __

__ ・ = f.hidden_field: follow_id, value: user.id: Vérifions le code source réellement complété. __

![Capture d'écran 2020-06-27 15.47.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606750/201d6a5e-3b2f-5e57-4155 -fd7326975490.png)

__ Identique au bouton de non-suivi, les données sont envoyées sous forme de paramètres [: relation] [: id_suivi]. __

__ ・ Maintenant que le bouton suivre / ne plus suivre a été créé, il est temps de définir le routage pour que ces données soient envoyées à l'action normalement! __


9. Ajoutez le routage au contrôleur de relations.

config/routes.rb


Rails.application.routes.draw do
  .
  .
  #<Autre routage omis>
  .
  .
  resources :relationships, only: [:create, :destroy]

Vérifiez les routes ajoutées avec la commande __ · $ rails routes | grep Relationship. __

$ rails routes | grep relationship
  relationships  POST   /relationships(.:format)                                                        relationships#create
  relationship   DELETE /relationships/:id(.:format)                                                             relationships#destroy

__ ・ Vous pouvez maintenant confirmer que vous pouvez suivre avec relations_path / unfollow avec relation_path. __


10. Placez un bouton Suivre / Ne plus suivre.

__ ・ Je voudrais le placer dans le fichier app / views / users / show.html.slim au cas où vous voudriez pouvoir suivre ou ne plus suivre lorsque vous passez à la page de l'autre utilisateur. __

ruby:app/views/users/show.html.slim


Page de profil utilisateur h1
p
  = "Nom: "
  = @user.username

#================Ajouter un bouton de suivi=============================

  = render 'relationships/follow_form', user: @user

#============================================================

p= link_to "Modifier le profil", edit_user_path(current_user)

__ · user: @user__: __ L'utilisateur décrit dans le partiel fait référence à @user défini dans l'action show. __

__- Le bouton a été placé, mais le bouton ne fonctionnera pas tel quel. En effet, comme mentionné précédemment, la variable d'instance @relationship et la variable d'instance @set_relationship doivent être définies dans l'action show. __


11.app/controllers/users_controller.rbのshowアクションに、インスタンス変数を定義する。

app/controllers/users_controller.rb


class UsersController < ApplicationController
  .
  .
  .
  def show
    @user = User.find(params[:id])
    @relationship = current_user.relationships.find_by(follow_id: @user.id)  
    @set_relationship = current_user.relationships.new
  end
  .
  .
  .
end

__ · @ Relationship = current_user.relationships.find_by (follow_id: @ user.id) __: __ Il s'agit de la variable d'instance référencée dans le formulaire de non-suivi. En récupérant ici les relations entre current_user et @user, vous pourrez envoyer des données comme les paramètres [: relation] [: follow_id] dans le form. __

__ · @ set_relationship = current_user.relationships.new __: __ Il s'agit de la variable d'instance référencée dans le formulaire à suivre. Je veux envoyer des données sous la forme de paramètres [: relation] [: follow_id], donc je crée une variable d'instance vide comme celle-ci. __

__ ・ Ceci termine l'implémentation de la fonction pour suivre / ne plus suivre les utilisateurs! Ensuite, nous allons implémenter une fonction pour afficher une liste d'utilisateurs qui nous suivent / utilisateurs qui nous suivent! __


Suivre la fonction d'affichage de la liste des utilisateurs / abonnés

1. Commencez par créer un lien vers la page suivante de la liste des utilisateurs / abonnés dans la vue.

__ · Ajouter un lien vers la page de la liste des abonnés / abonnés de l'utilisateur dans app / views / users / show.html.slim. __

ruby:app/views/users/show.html.slim


Page de profil utilisateur h1
p
  = "Nom: "
  = @user.username

#==============Lien vers la page de la liste des suiveurs / abonnés=================

  = link_to "Suivre: #{@user.followings.count}", followings_user_path(@user.id)
  = "/"
  = link_to "Disciple: #{@user.followers.count}", followers_user_path(@user.id)

#============================================================

  = render 'relationships/follow_form', user: @user
p= link_to "Modifier le profil", edit_user_path(current_user)

__ · Pour accéder aux abonnés / suiveurs, utilisez les suivants / suiveurs définis précédemment dans le fichier de modèle utilisateur. __

__ · @ user.followings.count __: __ Affiche le nombre d'utilisateurs que l'utilisateur suit. __ __ · followings_user_path (@ user.id) __: __ Je veux spécifier le chemin où l'URL est ʻusers /: id / followings`, donc écrivez comme indiqué sur la gauche. J'écrirai le routage plus tard afin que vous puissiez spécifier ce type de chemin. __

__ ・ L'accès à la page de la liste des abonnés est décrit de la même manière que l'accès à la page de la liste des utilisateurs suivants. __


2. Ajoutez une route à la page de liste de suiveurs / suiveurs.

config/routes.rb


Rails.application.routes.draw do
  .
  .
  .
  resources :users do
    get :followings, on: :member
    get :followers, on: :member
  end
  .
  .
  .
end

__ ・ Après avoir écrit comme ci-dessus, vérifiez le routage avec la commande $ rails routes | grep follow. __

$ rails routes | grep follow
  followings_user  GET    /users/:id/followings(.:format)                                                          users#followings
  followers_user   GET    /users/:id/followers(.:format)                                                           users#followers

__ ・ followings_user_path passera à la page de la liste des utilisateurs suivants, et followers_user_path passera à la page de la liste des abonnés, donc c'est OK. __

__ · Étant donné que l'action suivante et l'action Suiveurs sont imbriquées dans la ressource utilisateurs, définissez deux actions dans le contrôleur d'utilisateurs. __


3. Ajoutez l'action suivante et l'action Suiveurs au contrôleur des utilisateurs.

app/controllers/users_controller.rb


class UsersController < ApplicationController
  .
  .
  .
  def followings
    @user = User.find(params[:id])
    @users = @user.followings.all
  end

  def followers
    @user = User.find(params[:id])
    @users = @user.followers.all
  end
  .
  .
  .

__ · Dans l'action suivante, tous les utilisateurs suivis par @user sont acquis, et dans l'action Suiveurs, tous les abonnés de @user sont acquis. __


4. Créez une vue qui affiche une liste de followers / followers.

__ · Créez les fichiers followings.html.slim et followers.html.slim dans le répertoire app / views / users. __

ruby:app/views/users/followings.html.slim


h2 abonnés

- @users.each do |user|
  hr
  = "username: "
  = link_to user.username, user_path(user.id)

ruby:app/views/users/followers.html.slim


h2 abonnés

- @users.each do |user|
  hr
  = "username: "
  = link_to user.username, user_path(user.id)

__ ・ Ceci termine la création de la page de suivi des utilisateurs / listes d'utilisateurs! __

Articles que j'ai utilisés comme référence

Comment créer une fonction de suivi avec Rails

Recommended Posts

[Rails] Je vais expliquer la procédure d'implémentation de la fonction follow en utilisant form_with.
[Rails] Implémentation de la fonction de recherche en utilisant le ransack de gem
[Rails] Implémentation de la fonction d'agrandissement d'image à l'aide de lightbox2
J'ai essayé d'utiliser la fonction Server Push de Servlet 4.0
[Rails] Implémentation de la fonction de catégorie multicouche en utilisant l'ascendance "Préparation"
[Rails] Implémentation de la fonction de catégorie multicouche à l'aide de l'ascendance "seed edition"
[Rails] Implémentation de la fonction de catégorie
[Rails] Implémentation de la fonction tutoriel
[Rails] Implémentation d'une fonction similaire
[Rails] Implémentation de la fonction de catégorie multicouche à l'aide de l'ascendance "Formulaire de création"
[Rails] Implémentation asynchrone de la fonction similaire
[Rails] Implémentation de la fonction de prévisualisation d'image
[Rails] À propos de la mise en œuvre de la fonction similaire
[Rails] Commentaire mémo de procédure d'implémentation
Je vais expliquer l'imbrication des déclarations qui tuent les débutants
J'ai essayé d'utiliser la fonction de cache d'Application Container Cloud Service
[Rails] Implémentation de la fonction coupon (avec fonction de suppression automatique par traitement par lots)
[Rails] Implémentation de la fonction de balise à l'aide de la fonction agit-as-taggable-on et de la fonction de complétion d'entrée de balise à l'aide de tag-it
Implémentation de la fonction d'authentification des utilisateurs à l'aide de devise (2)
[Ruby on Rails] Suivez l'implémentation de la fonction: bidirectionnelle
Implémentation de la fonction d'authentification des utilisateurs à l'aide de devise (1)
Rails [Pour les débutants] Implémentation de la fonction de commentaire
Où la fonction de suivi est implémentée
Échafaudage de procédure d'implémentation de fonction CRUD de base
Implémentation de la fonction d'authentification des utilisateurs à l'aide de devise (3)
[Ruby on rails] Implémentation d'une fonction similaire
[Rails] J'écrirai très attentivement le mécanisme et la méthode d'utilisation de payjp (API) (enregistrement Kureka)
[Rails] Procédure d'implémentation de la fonction pour taguer les posts sans gem + la fonction pour affiner et afficher les posts par tags
Implémentation de la fonction de connexion Ruby on Rails (Session)
[Rails] Quand j'utilise form_with, l'écran se fige! ??
[JQuery] Procédure d'implémentation de la fonction de saisie semi-automatique [Java / Spring]
[Rails] J'ai créé une fonction de brouillon en utilisant enum
Les rails suivent la fonction
[Rails / appareil] Implémentation de la fonction d'édition des informations de compte / Procédure de changement de destination de la redirection
[Rails] Mise en œuvre du classement des nombres PV à l'aide de l'impressionniste
[Rails] Implémentation du diaporama d'images à l'aide de Bootstrap 3
[Rails] Procédure de mise en œuvre lorsque des fonctions publiques / privées sont ajoutées à la fonction de publication
J'ai essayé d'utiliser le profileur d'IntelliJ IDEA
[Rails] Implémentation de la fonction glisser-déposer (avec effet)
Implémentation de la fonction de connexion Ruby on Rails (édition de devise)
J'ai résumé le format d'affichage de la réponse JSON de Rails
Rails6: saisissez les données initiales d'ActionText à l'aide de seed
Je ne peux pas sortir de l'écran de la console Rails db
Essayez d'utiliser l'attribut de requête Ruby on Rails
[rails] gem'payjp'implementation procedure
Suivez l'implémentation de la fonction (Ajax)