[RUBY] Communication asynchrone dans le champ de commentaire interactif

introduction

Je fréquente actuellement une école de programmation appelée TECH CAMP. Je développe une application clone Flima, mais j'ai décidé d'implémenter une section de commentaires. La section des commentaires de l'application Furima a une apparence de dialogue entre «l'exposant» et «les autres», donc j'écrirai principalement sur les points que j'ai élaborés lors de cette communication asynchrone.

Ce que vous voulez réaliser

Je voudrais mettre à jour le champ de commentaire par communication asynchrone afin que l'apparence de la vue soit ramifiée entre le vendeur et d'autres personnes (clients). L'échantillon complété est le suivant.

★ Lorsque le client poste

3c528fb36058573b4181cbd20e09df22.gif

★ Une fois publié par le vendeur

81970b7d86e801a61e0b752d6c4322df.gif

procédure

Cette fois, en supposant que la publication normale des commentaires est terminée, je vais me concentrer sur la désynchronisation ultérieure et écrire la procédure.

Modifier l'action de création du contrôleur

Il y a deux points.

Le premier point est que les variables d'instance "@item" et "@comment" sont créées lors de l'action de création. @item extrait l'enregistrement du produit commenté et @comment stocke l'enregistrement de commentaire enregistré. Ces variables d'instance seront ensuite utilisées par jbuilder pour la jsonisation.

Le deuxième point est que "format.html" est ajouté dans respond_to afin que si jQuery n'est pas chargé, il puisse répondre même au format HTML. Comme cela sera décrit plus loin, il existe des cas où le fichier js ne se charge pas correctement lors de l'utilisation simultanée de turbolinks. Bien sûr, ce serait mieux si cela pouvait être géré correctement, mais je pense qu'il y a beaucoup de gens qui développent l'équipe pour la première fois, alors j'ai pensé qu'une telle assurance serait nécessaire, alors je l'ai écrite.

comments_controller.rb


class CommentsController < ApplicationController
  def create
    @item = Item.find(params[:item_id])
    @comment = Comment.create(comment_params)
    respond_to do |format|
      format.html { redirect_to item_path(params[:item_id]) }
      format.json
    end
  end

~ Action de destruction omise cette fois ~

  private
  def comment_params
    params.require(:comment).permit(:comment).merge(user_id: current_user.id, item_id: params[:item_id])
  end
end

Créer un nouveau fichier jbuilder

Créez un fichier jbuilder. Il y a aussi deux points ici. Le premier point est "json.comment_user_id" sur la 3ème ligne et "json.item_user_id" sur la 7ème ligne. Après cela, branchez conditionnellement la vue à ajouter selon qu'il s'agit d'un vendeur ou non dans le fichier js. Si l'id_utilisateur dans la table des articles et l'id_utilisateur dans la table des commentaires correspondent, vous êtes le vendeur.

Le deuxième point est "json.comment_id" sur la première ligne et "json.comment_item_id" sur la cinquième ligne. Ceci est utilisé dans le lien \ lors de la suppression d'un commentaire. Remplacez-les dans la partie id de l'URL à supprimer pour en faire le lien correct.

ruby:views/comments/create.json.jbuilder


json.comment_id      @comment.id
json.comment         @comment.comment
json.comment_user_id @comment.user_id
json.name            @comment.user.nickname
json.comment_item_id @comment.item_id
json.item_id         @item.id
json.item_user_id    @item.user_id

Créer un fichier js

Ce sera plus long, mais je posterai le code complet du code complété.

comment.js


$(function(){
  function buildHTML(comment){
    var html = `<div class="mainShow__box__content__top__commentBox__comments__comment">
                  <div class="profile">
                    <div class="profile__name">
                      ${comment.name}
                    </div>
                    <div class="profile__right">
                      <div class="image">
                        <i class="fas fa-user-circle"></i>
                      </div>
                      <div class="seller_or_buyer">
Vendeur
                      </div>
                    </div>
                  </div>
                  <div class="comment">
                    <div class="comment__text">
                      ${comment.comment}
                    </div>
                    <div class="comment__bottom">
                      <div class="comment__date">
                        <i class="far fa-clock"></i>
aujourd'hui
                      </div>
                      <div class="comment__trash">
                        <a item_id="@item" rel="nofollow" data-method="delete" href="/items/${comment.item_id}/comments/${comment.comment_id}"><i class="fa fa-trash"></i>
                        </a>
                      </div>
                    </div>
                  </div>
                </div>`
    return html;
  }

  function buildHTMLother(comment){
    var html = `<div class="mainShow__box__content__top__commentBox__comments__comment--other">
                  <div class="profile">
                    <div class="profile__right">
                      <div class="image">
                        <i class="far fa-user-circle"></i>
                      </div>
                      <div class="seller_or_buyer">
Client
                      </div>
                    </div>
                    <div class="profile__name">
                      ${comment.name}
                    </div>
                  </div>
                  <div class="comment">
                    <div class="comment__text">
                      ${comment.comment}
                    </div>
                    <div class="comment__bottom">
                      <div class="date">
                        <i class="far fa-clock"></i>
aujourd'hui
                      </div>
                      <div class="comment__icon">
                        <div class="flag">
                          <i class="far fa-flag"></i>
                        </div>
                        <div class="trash">
                          <a item_id="@item" rel="nofollow" data-method="delete" href="/items/${comment.item_id}/comments/${comment.comment_id}"><i class="fa fa-trash"></i></a>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>`
    return html;
  }

  $('#comment_form').on ('submit',function(e){
    e.preventDefault();
    var formData = new FormData(this);
    var url = $(this).attr('action');
    $.ajax({
      url: url,
      type: "POST",
      data: formData,
      dataType: 'json',
      processData: false,
      contentType: false
    })
    .done(function(data){
      if (data.comment_user_id == data.item_user_id) {
        var html = buildHTML(data);
        $('#comments').append(html);
        $('.text_area').val('');
        $('.comment_btn').prop('disabled', false);
      } else {
        var html = buildHTMLother(data);
        $('#comments').append(html);
        $('.text_area').val('');
        $('.comment_btn').prop('disabled', false);
      }
    })
    .fail(function(){
      alert('error');
    })
  })
});

Dans la première moitié, le HTML de la vue à ajouter est décrit. Cette fois, la vue est différente entre le vendeur et les autres personnes, et le CSS est également légèrement différent, nous avons donc préparé deux types. S'il s'agit d'un commentaire du vendeur, il sera ajouté par la méthode buildHTML, et si ce n'est pas le cas, il sera ajouté par la méthode buildHTMLother. Dans le HTML, en plus du corps du commentaire et du surnom, l'identifiant est également inclus dans le lien de la méthode de suppression. Vous pouvez maintenant supprimer immédiatement les commentaires ajoutés par communication asynchrone.

Dans la seconde moitié, le contenu d'exécution spécifique du fichier js est écrit. Si le résultat du traitement est terminé, l'instruction if est utilisée pour déterminer conditionnellement si le vendeur est un vendeur ou non.

Prend en charge les turbolinks

Le fichier js peut ne pas être lu normalement lorsque les turbolinks sont utilisés ensemble. Pour une solution à cela, l'article écrit par une autre personne a été utile. Jusqu'à ce que je trouve cet article, je ne pensais pas que les turbolinks étaient la cause en premier lieu, donc c'était une révélation.

Comment résoudre js ne fonctionne pas à moins que la page ne soit chargée avec Rails @ryico

La pile d'aujourd'hui

Jusqu'à présent, la communication asynchrone par ajax était reconnue que les données de commentaire publiées étaient renvoyées par json. Cependant, au lieu de cela, j'ai compris que la variable d'instance créée lors de l'action de création est traitée par jbuilder, convertie en json et renvoyée. Si vous souhaitez utiliser l'enregistrement de la table des éléments comme cette fois, vous pouvez créer @item.

Recommended Posts

Communication asynchrone dans le champ de commentaire interactif
Histoire de refactoring de rails apprise sur le terrain
Fonction de publication implémentée par communication asynchrone dans Rails
J'ai essayé d'implémenter la fonction similaire par communication asynchrone
[Rails] J'ai implémenté le message d'erreur de validation avec une communication asynchrone!