Ich habe eine Team-Chat-Funktion mit Action Cable im Portfolio erstellt, damit ich sie ausgeben kann.
Ich habe auf den folgenden Artikel verwiesen. Vielen Dank. ・ Mit Schienen 5 + Aktionskabel herstellen! Einfache Chat-App (aus dem Demo-Video von DHH) ・ [Rails 6.0] Erstellen Sie einen Echtzeit-Chat mit Action Cable und Devises gierigem Set (überarbeitete Version)
Passen Sie den Code im Referenzartikel an, um einen Chat für jedes Team zu senden. Dieses Mal erstellen wir eine Chat-Aktion auf dem Team-Controller, damit wir Chats senden können. Erstellen Sie andere Teile als das Aktionskabel gemäß der MVC-Struktur.
model Das Modell beschreibt die Viele-zu-Viele-Beziehung zwischen dem Teammodell und dem Benutzermodell. Darüber hinaus wird das Nachrichtenmodell, das den Inhalt des Chats darstellt, als Modell der Zwischentabelle zwischen dem Benutzer und dem Team erstellt.
app/models/team.rb
class Team < ApplicationRecord #Teammodell
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 #Fügen Sie ein Benutzersymbol in Active Storage hinzu
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 Der Controller hat eine Chat-Aktion innerhalb des Teams erstellt. Erhalten Sie die Team-ID über den Link, suchen Sie in der Team-Klasse, rufen Sie den Chat des Teams ab und übergeben Sie ihn zur Anzeige.
app/controllers/teams_controller.rb
def chat
@team = Team.find(params[:id])
messages = @team.messages
end
view Seit ich Bootstrap angewendet habe, verwende ich Container, Alert usw. Grundsätzlich wird der empfangene Chat auf dem Bildschirm angezeigt, indem eine Nachricht teilweise gerendert wird. Wir haben auch ein Formular zum Senden von Chats.
html:app/views/teams/chat.html.erb
<h1 id="chat" data-team_id="<%= @team.id %>">
<%= @team.name %>Chatraum
</h1>
<div class="container">
<% if @team.members.count == 1 %>
<div class="alert alert-danger" role="alert">
Es gibt keine Teammitglieder, mit denen Sie chatten können. Fügen Sie Mitglieder aus dem Teambildschirm hinzu
</div>
<% end %>
<form class="form-group">
<label>Plaudern:</label>
<input type="text" data-behavior="team_speaker", placeholder="Inhalt", 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>
Implementieren Sie von hier aus das Aktionskabel. Erstellen Sie zunächst einen Teamkanal. Verzeichnisse und Dateien werden für den Kanal erstellt.
$ rails g channel team
coffeescript Beschreiben Sie zunächst die Einstellungen für die Überwachung des Servers über den Browser. Verwenden Sie jQuery, um die Team-ID anzuzeigen und einen Kanal zum Abonnieren zu erstellen.
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) ->
#Empfangen Sie den Chat, der von der Sprechmethode auf der Kanalseite empfangen wurde
$('#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 Beschreiben Sie als Nächstes die Einstellungen für die Überwachung des Browsers vom Server aus. Die @perform speak des Browsers ruft die serverseitige Sprechaktion auf. Die Sprechaktion erstellt eine Instanz der Nachrichtenklasse basierend auf den vom Browser empfangenen Informationen.
app/channels/team_channel.rb
class TeamChannel < ApplicationCable::Channel
def subscribed
stream_from "team_channel_#{params['team_id']}" #Zeigen Sie, welches Team Sie überwachen
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
Ich verwende current_user im Kanal, aber dafür muss ich den folgenden Code hinzufügen.
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
Lässt den Job ausführen, wenn eine Instanz im Nachrichtenmodell erstellt wird (nach dem Festschreiben).
app/models/message.rb
class Message < ApplicationRecord
belongs_to :user
belongs_to :team
after_create_commit { MessageBroadcastJob.perform_later self } #Nachtrag
end
job Beschreiben der Einstellungen zum Senden der erstellten Nachricht vom Job an den Browser. Erstellen Sie zunächst einen Nachrichtenübertragungsjob mit dem Befehl Rails.
$ rails g job MessageBroadcast
Wenn Sie ActiveStorage verwenden und in ApplicationController.renderer nicht http_host angeben, führt das Bildreferenzziel zu einem Fehler. Wenn Sie in der Produktion eine URL verwenden möchten, die mit https: // anstelle von http: // beginnt, müssen Sie https: true angeben.
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_Hostnummer', #Local, localhost:3000. Je nach Produktionsumgebung geändert
#https: true https://Für URLs, die mit beginnen, müssen Sie diesen Code hinzufügen
)
renderer.render(partial: 'messages/message', locals: { message: message })
end
end
Durch diesen Job wird der Teil der Nachricht an den Empfang von Kaffeeskript übergeben und in Echtzeit wiedergegeben.
Ich fand ActionCable kompliziert, konnte aber die Weitergabe von Daten anhand von Referenzen verfolgen und verstehen. Aufgrund dieser Erfahrung wurde mir erneut klar, dass es wichtig ist, den Datenfluss einzeln zu verfolgen, auch wenn er kompliziert aussieht, und es ist die beste Verknüpfung, um binding.pry auf der Serverseite und Debugger auf der Browserseite zu verwenden. ..
Recommended Posts