J'ai créé une fonction de chat en équipe avec Action Cable dans le portefeuille, je vais donc la publier.
J'ai fait référence à l'article suivant. Merci beaucoup. ・ Fabriqué avec Rails 5 + Action Cable! Application de chat simple (de la vidéo de démonstration de DHH) ・ [Rails 6.0] Créez une discussion en temps réel avec Action Cable et l'ensemble gourmand de Devise (version révisée)
Modifiez le code de l'article de référence pour envoyer une discussion à chaque équipe. Cette fois, nous allons créer une action de chat sur le contrôleur d'équipe afin que nous puissions envoyer des chats. Créez les pièces autres que le câble d'action selon la structure MVC.
model Le modèle décrit la relation plusieurs-à-plusieurs entre le modèle d'équipe et le modèle utilisateur. De plus, le modèle de message, qui est le contenu du chat, est créé comme modèle de la table intermédiaire entre l'utilisateur et l'équipe.
app/models/team.rb
class Team < ApplicationRecord #Modèle d'équipe
  belongs_to :owner, class_name: 'User', foreign_key: :owner_id
  has_many :team_assigns, dependent: :destroy 
  has_many :members, through: :team_assigns, source: :user
  has_many :messages, dependent: :destroy
end
app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  has_one_attached :icon #Ajouter une icône d'utilisateur dans Active Storage
  has_many :team_assigns, dependent: :destroy
  has_many :teams, through: :team_assigns, source: :team
  has_one :owner_team, class_name: 'Team', foreign_key: :owner_id, dependent: :destroy
  has_many :messages, dependent: :destroy
end
app/models/team_assign.rb 
class TeamAssign < ApplicationRecord
  belongs_to :team
  belongs_to :user
end
app/models/message.rb
class Message < ApplicationRecord
  belongs_to :user
  belongs_to :team
end
controller Le contrôleur a créé une action de chat au sein de l'équipe. Recevez l'ID d'équipe à partir du lien, recherchez dans la classe Team, obtenez le chat de l'équipe et transmettez-le à la vue.
app/controllers/teams_controller.rb
  def chat
    @team = Team.find(params[:id])
    messages = @team.messages
  end
view Depuis que j'ai appliqué le bootstrap, j'utilise un conteneur, une alerte, etc. Fondamentalement, le chat reçu est affiché à l'écran en rendant un message partiel. Nous avons également un formulaire pour envoyer des chats.
html:app/views/teams/chat.html.erb
<h1 id="chat" data-team_id="<%= @team.id %>">
  <%= @team.name %>Tchat
</h1>
<div class="container">
  <% if @team.members.count == 1 %>
    <div class="alert alert-danger" role="alert">
Il n'y a aucun membre de l'équipe avec qui discuter. Ajouter des membres depuis l'écran d'équipe
    </div>
  <% end %>
  <form class="form-group">
    <label>bavarder:</label>
    <input type="text" data-behavior="team_speaker", placeholder="Contenu", class="form-control">
  </form>
  <div id="messages_<%= @team.id %>">
    <ul class="list-group">
      <%= render @messages %>
    </ul>
  </div>
</div>
html:app/views/messages/_message.html.erb
<div class="message">
  <li class="list-group-item">
    <div class="row">
      <div class="col-md-2">
        <% if message.user.icon.attached? %>
          <%= image_tag message.user.icon.variant(resize:'50x50').processed %>
        <% end %>
        <p><%= message.user.name %></p>
      </div>
      <div class="col-md-10">
        <small class="text-muted"><%= l message.created_at, format: :short %></small><br>
        <%= message.content %>
      </div>
    </div>
  </li>
</div>
De là, implémentez Action Cable. Tout d'abord, créez un canal d'équipe. Des répertoires et des fichiers sont créés pour le canal.
$ rails g channel team
coffeescript Tout d'abord, décrivez les paramètres de surveillance du serveur à partir du navigateur. Utilisez jQuery pour obtenir l'ID d'équipe de la vue et créer un canal auquel vous abonner.
app/assets/javascripts/channels/team.coffee
App.team = App.cable.subscriptions.create {
  channel: "TeamChannel",
  team_id: $("#chat").data("team_id")}, 
  connected: ->
    # Called when the subscription is ready for use on the server
  disconnected: ->
    # Called when the subscription has been terminated by the server
  received: (data) ->
    #Recevoir le chat reçu par la méthode Speak du côté Channel
    $('#messages_'+data['team_id']).prepend data['message']
  speak: (message) ->
    team_id = $('#chat').data('team_id')
    @perform 'speak', message: message, team_id: team_id
$(document).on 'keypress', '[data-behavior~=team_speaker]', (event) ->
  if event.keyCode is 13 # return = send
    App.team.speak event.target.value
    event.target.value = ''
    event.preventDefault()
channel.rb Ensuite, décrivez les paramètres de surveillance du navigateur à partir du serveur. @Perform speak du navigateur appelle l'action de parole côté serveur. L'action de parole crée une instance de la classe de message en fonction des informations reçues du navigateur.
app/channels/team_channel.rb
class TeamChannel < ApplicationCable::Channel
  def subscribed
    stream_from "team_channel_#{params['team_id']}" #Montrez quelle équipe vous surveillez
  end
  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
  def speak(data)
    message = Message.create!(
      content: data['message'],
      team_id: data['team_id'],
      user_id: current_user.id
    )
  end
end
J'utilise current_user dans le canal, mais pour cela, je dois ajouter le code suivant.
app/channels/application_cable/connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user
    def connect
      self.current_user = find_verified_user
    end
    private
      def find_verified_user
        verified_user = User.find_by(id: env['warden'].user.id)
        return reject_unauthorized_connection unless verified_user
        verified_user
      end
  end
end
Fait exécuter la tâche lorsqu'une instance est créée dans le modèle Message (après validation).
app/models/message.rb
class Message < ApplicationRecord
  belongs_to :user
  belongs_to :team
  after_create_commit { MessageBroadcastJob.perform_later self } #Postscript
end
job Décrivez les paramètres pour envoyer le message créé du travail au navigateur. Commencez par créer un travail de diffusion de message à partir de la commande rails.
$ rails g job MessageBroadcast
Si vous utilisez ActiveStorage et que vous ne spécifiez pas http_host dans ApplicationController.renderer, la destination de référence d'image entraînera une erreur. Si vous souhaitez utiliser une URL commençant par https: // au lieu de http: // en production, vous devez spécifier https: true.
app/jobs/message_broadcast_job.rb
class MessageBroadcastJob < ApplicationJob
  queue_as :default
  def perform(message)
    ActionCable.server.broadcast(
      "team_channel_#{message.team_id}",
      message: render_message(message),
      team_id: message.team_id
    )
  end
  private
    def render_message(message)
      renderer = ApplicationController.renderer.new(
        http_host: 'http_numéro d'hôte', #Local, localhost:3000. Modifié en fonction de l'environnement de production
    #https: true          https://Pour les URL commençant par, vous devez ajouter ce code
      )
      renderer.render(partial: 'messages/message', locals: { message: message })
    end
end
Par ce travail, la partie du message est transmise à la réception de coffeescript et réfléchie en temps réel.
Je pensais qu'ActionCable était compliqué, mais j'ai pu suivre et comprendre le passage des données par référence. De cette expérience, j'ai réalisé à nouveau qu'il est important de suivre le flux de données un par un même si cela semble compliqué, et c'est le meilleur raccourci pour utiliser binding.pry côté serveur et débogueur côté navigateur. ..
Recommended Posts