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