Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する

Facebookにアクセスして、ページを更新せずに通知を受け取ったことはありますか?この種のリアルタイム機能は、状態管理を介したReactなどのJavaScriptフレームワークを使用するほとんどのアプリケーションで実現されます。これらのアプリケーションのほとんどは、データをリアルタイムで更新するために使用中にページをリロードする必要がないため、シングルページアプリケーションとして機能します。Railsアプリケーションは、通常、ページのリロードが必要であるという意味で、ステートレスでした。アプリケーションの現在の状態。たとえば、劇場で利用可能な映画のリストを表示するRailsアプリを使用していて、映画が管理者によって追加された場合、ページを更新しない限り、新しく追加された映画はダッシュボードに表示されません。

なぜActionCableなのか?

ActionCableはこのギャップを埋め、Railsアプリケーションでリアルタイムの更新とこの動的な機能を利用できるようにします。 WebSocketと呼ばれる通信プロトコルを利用して、パフォーマンスとスケーラブルを維持しながら、アプリケーションに状態を導入します。これにより、ユーザーはページを更新しなくてもダッシュボードで更新されたコンテンツを取得できます。

マジックオブターボレール

TurboRailsは、ターボドライブ、ターボフレーム、およびターボストリームで構成されています。ターボフレームでラップされたページの一部からリクエストが送信されると、同じIDを持っている場合、HTML応答によって、出力されたフレームが置き換えられます。一方、ターボストリームでは、これらの部分的なページ更新をWeb上で有効にします。ソケット接続。 ActionCableはこれらの更新をチャネルからブロードキャストし、Turboストリームはこのチャネルのサブスクライバーを作成して更新を配信します。その結果、モデルの変更に応じて非同期更新を直接作成できます。

構築しようとしているもの

この記事の目的は、Turboが舞台裏でActionCableと連携して、Rails6アプリでリアルタイムの更新をブロードキャストおよび表示する方法を紹介することです。そのため、どのユーザーでもチャットルームを作成でき、すべてのユーザーがそのルームにメッセージを送信したり、リアルタイムで更新を受信したりできるチャットアプリを構築します。また、ユーザー同士がプライベートにチャットできるようにします。グループチャットの招待は実装しません。 TurboやActionCableではなく、追加のデータベース設計のみが含まれるため、これらはこのブログ投稿の範囲を超えています。ただし、このレッスンの後、さらに先に進むことを選択した場合は、簡単なことになるはずです。

これはどのように見えるべきですか、それとも何を伴うべきですか?

  • 既存のすべてのチャットルームとユーザーを一覧表示するインデックスページ。
  • このページは、新しいユーザーが登録したとき、または新しい部屋が作成されたときに動的に更新される必要があります。
  • 新しいチャットルームを作成するためのフォームがあります。
  • チャットルームにいるときにメッセージを作成するためのメッセージチャットボックス。
始めるための7つの簡単なステップ

このアプリでは、ユーザーは一意のユーザー名を使用してのみログインする必要があります。これは、セッションを使用して実現されます。

1。新しいRailsアプリを作成する

rails new chatapp
cd chatapp

2。ユーザーモデルを作成して移行する

rails g model User username
rails db:migrate

次に、すべてのユーザー名を所有者に一意にするため、ユーザー名に一意の検証を追加します。また、ユーザーが自分自身とチャットしたくないため、ユーザーリストの現在のユーザーを除くすべてのユーザーをフェッチするスコープを作成します:)

#app/models/user.rb
class User < ApplicationRecord
  validates_uniqueness_of :username
  scope :all_except, ->(user) { where.not(id: user) }
end

3。チャットルームモデルを作成する

チャットルームには名前があり、プライベートチャットルーム(2人のユーザー間のプライベートチャット用)またはパブリック(すべてのユーザーが利用可能)にすることができます。これを示すために、is_privateを追加します 部屋のテーブルへの列。

 rails g model Room name:string is_private:boolean

このファイルを移行する前に、デフォルト値をis_privateに追加します 特に明記されていない限り、作成されたすべての部屋がデフォルトで公開されるように列を作成します。

class CreateRooms < ActiveRecord::Migration[6.1]
  def change
    create_table :rooms do |t|
    t.string :name
    t.boolean :is_private, :default => false

    t.timestamps

    end
  end
end

この手順の後、コマンドrails db:migrateを使用してファイルを移行します。 。また、nameプロパティの一意性検証と、ルームリストのすべてのパブリックルームをフェッチするスコープを追加する必要があります。

#app/models/room.rb
class Room < ApplicationRecord
  validates_uniqueness_of :name
  scope :public_rooms, -> { where(is_private: false) }
end

4。スタイリングを追加

このアプリに最小限のスタイルを追加するために、ブートストラップCDNをapplication.html.erbファイルに追加します

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

5。認証を追加

アプリに認証を追加するには、current_userが必要です 常に可変。記載されているファイルに次のコードをアプリに追加して、認証を有効にしましょう。

#app/controllers/application_controller.rb
helper_method :current_user

def current_user
  if session[:user_id]
    @current_user  = User.find(session[:user_id])
  end
end

def log_in(user)
  session[:user_id] = user.id
  @current_user = user
  redirect_to root_path
end

def logged_in?
  !current_user.nil?
end

def log_out
  session.delete(:user_id)
  @current_user = nil
end
#app/controllers/sessions_controller.rb
class SessionsController < ApplicationController

  def create
    user = User.find_by(username: params[:session][:username])
    if user
      log_in(user)
    else
      render 'new'
    end
  end

  def destroy
    log_out if logged_in?
    redirect_to root_path
  end

end
#app/views/sessions/new.html.erb
<%= form_for (:session) do |f| %>
  <%= f.label :username, 'Enter your username' %>
  <%= f.text_field :username, autocomplete: 'off' %>
  <%= f.submit 'Sign in' %>
<% end %>

次のルートをroutes.rbファイルに追加します。

#routes.rb
Rails.application.routes.draw do
  get '/signin', to: 'sessions#new'
  post '/signin', to: 'sessions#create'
  delete '/signout', to: 'sessions#destroy'
end

6。コントローラを作成する

rails g controller Rooms indexを使用してRoomsControllerを作成します ユーザーと部屋のリストの変数をインデックスメソッドに追加します。

class RoomsController < ApplicationController

  def index
    @current_user = current_user
    redirect_to '/signin' unless @current_user
    @rooms = Room.public_rooms
    @users = User.all_except(@current_user)
  end
end

7。ルートを設定する

部屋、ユーザー、ルートルートをroutes.rbに追加します ランディングページがすべての部屋とユーザーを一覧表示するインデックスページになり、選択した任意の部屋に移動できるようにします。

#routes.rb
  resources :rooms
  resources :users
  root 'rooms#index'
ビューの設定

Turboの「魔法」の最初の紹介は、新しく追加された部屋または新しくサインアップしたユーザーの場合にダッシュボードでリアルタイムの更新を受信することです。これを実現するために、まず、2つのパーシャルを作成します。_room.html.erb 各部屋と_user.html.erbを表示します 各ユーザーを表示します。このリストをindex.html.erbにレンダリングします これはランディングページであるため、RoomsControllerの作成時に作成されたファイル。

# app/views/rooms/_room.html.erb
<div> <%= link_to room.name, room %> </div>
# app/views/users/_user.html.erb
<div> <%= link_to user.username, user %> </div>

これらのファイルをindex.html.erbにレンダリングします。 ファイルを直接参照するのではなく、コレクションをフェッチする変数をレンダリングします。 RoomsControllerの変数@usersを思い出してください。 および@rooms すでに定義されています。

#app/views/rooms/index.html.erb
<div class="container">
  <h5> Hi <%= @current_user.username %> </h5>
  <h4> Users </h4>
  <%= render @users %>
  <h4> Rooms </h4>
  <%= render @rooms %>
</div>

コンソールで、次のコマンドを実行します。

Room.create(name: 'music')
User.create(username: 'Drake')
User.create(username: 'Elon')

rails sを使用してRailsサーバーの電源を入れます 。サインインするように求められます。上で作成したユーザーのユーザー名を使用してこれを行います。新しく作成した部屋と、サインインしなかったユーザーが下の画像に示すように表示されます。

ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する

ターボの紹介

リアルタイムの更新を実現するには、Turboをインストールする必要があります。

bundle add turbo-rails
rails turbo:install

Redisがインストールされていない場合は、次のコマンドを実行します。

sudo apt install redis-server
#installs redis if you don't have it yet
redis-server
#starts the server

turbo-railsをインポートします application.jsimport "@hotwired/turbo-rails"を使用したファイル

次に、モデルに特定の指示を追加し、新しく追加されたインスタンスを特定のチャネルにブロードキャストするようにモデルに依頼します。このブロードキャストは、後で説明するように、ActionCableによって行われます。

#app/models/user.rb
class User < ApplicationRecord
  validates_uniqueness_of :username
  scope :all_except, ->(user) { where.not(id: user) }
  after_create_commit { broadcast_append_to "users" }
end

ここでは、ユーザーの新しいインスタンスが作成されるたびに、ユーザーモデルに「users」というチャネルにブロードキャストするように依頼しています。

#app/models/room.rb
class Room < ApplicationRecord
  validates_uniqueness_of :name
  scope :public_rooms, -> { where(is_private: false) }
  after_create_commit {broadcast_append_to "rooms"}
end

ここでは、部屋の新しいインスタンスが作成されるたびに、部屋モデルに「部屋」と呼ばれるチャネルにブロードキャストするように依頼しています。

コンソールがまだ起動していない場合は起動するか、reload!を使用します すでに稼働している場合はコマンド。これらのいずれかの新しいインスタンスを作成した後、ActionCableは、追加されたインスタンスをテンプレートとして割り当てられた部分を使用して、ターボストリームとして指定されたチャネルにブロードキャストすることがわかります。新しく追加された部屋の場合、部分的な_room.html.erbをブロードキャストします。 以下に示すように、新しく追加されたインスタンスに対応する値を使用します。

ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する

ただし、問題は、ブロードキャストされたテンプレートがダッシュボードに表示されないことです。これは、ActionCableによってブロードキャストされたものをすべて受信して追加できるように、ブロードキャストのレシーバーをビューに追加する必要があるためです。これを行うには、turbo_stream_fromを追加します。 タグ、ブロードキャストの受信を希望するチャネルを指定します。上の画像に見られるように、ブロードキャストされたストリームにはターゲット属性があり、これはストリームが追加されるコンテナのIDを指定します。これは、ブロードキャストされたテンプレートが、追加する「部屋」のIDを持つコンテナを検索することを意味します。したがって、インデックスファイルに上記のIDを持つdivを含めます。これを実現するには、index.html.erbに ファイルの場合、<%= render @users %>を置き換えます と:

<%= turbo_stream_from "users" %>
<div id="users">
  <%= render @users %>
</div>

および<%= render @rooms %>

<%= turbo_stream_from "rooms" %>
<div id="rooms">
  <%= render @rooms %>
</div>

この瞬間、ターボの魔法を体験することができます。ページを更新して、コンソールから新しいユーザーとルームを追加し始め、それらがリアルタイムでページに追加されるのを見ることができます。イッピー!!!

コンソールから新しい部屋を作成するのにうんざりしていませんか?ユーザーが新しい部屋を作成できるフォームを追加しましょう。

#app/views/layouts/_new_room_form.html.erb
<%= form_with(model: @room, remote: true, class: "d-flex" ) do |f| %>
  <%= f.text_field :name, class: "form-control", autocomplete: 'off' %>
  <%= f.submit data: { disable_with: false } %>
<% end %>

上記のフォームでは、@room が使用されていますが、コントローラーではまだ定義されていません。したがって、これを定義して、RoomsControllerのインデックスメソッドに追加します。

@room = Room.new

作成ボタンをクリックすると、RoomsControllerのcreateメソッドにルーティングされますが、現在は存在していません。したがって、追加する必要があります。

#app/controllers/rooms_controller.rb
def create
  @room = Room.create(name: params["room"]["name"])
end

このフォームを部分的にレンダリングすることで、このフォームをインデックスファイルに追加できます。

<%= render partial: "layouts/new_room_form" %>

また、いくつかのブートストラップクラスを追加して、ページを部屋とユーザーのリスト用の部分とチャット用の部分に分割することもできます。

<div class="row">
  <div class="col-md-2">
    <h5> Hi <%= @current_user.username %> </h5>
    <h4> Users </h4>
    <div>
      <%= turbo_stream_from "users" %>
      <div id="users">
        <%= render @users %>
      </div>
    </div>
    <h4> Rooms </h4>
    <%= render partial: "layouts/new_room_form" %>
    <div>
      <%= turbo_stream_from "rooms" %>
      <div id="rooms">
        <%= render @rooms %>
      </div>
    </div>
  </div>
  <div class="col-md-10 bg-dark">
    The chat box stays here
  </div>
</div>

ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する 追加された部屋の画像がリアルタイムで更新されます

これで、新しい部屋を作成すると、これらの部屋が作成され、ページがリアルタイムで更新されていることがわかります。また、送信するたびにフォームがクリアされないことにも気付いたと思います。この問題は、後で刺激を使用して処理します。

グループチャット

グループチャットの場合、個々の部屋にルーティングできる必要がありますが、同じページにとどまります。これを行うには、インデックスページに必要なすべての変数をRoomsController showメソッドに追加し、インデックスページを静止させます。

#app/controllers/rooms_controller.rb
def show
  @current_user = current_user
  @single_room = Room.find(params[:id])
  @rooms = Room.public_rooms
  @users = User.all_except(@current_user)
  @room = Room.new

  render "index"
end

@single_roomという名前の追加の変数 showメソッドに追加されました。これにより、ルーティング先の特定の部屋が得られます。したがって、部屋の名前がクリックされたときに移動した部屋の名前を示す条件ステートメントをインデックスページに追加できます。これは、クラス名col-md-10でdiv内に追加されます 、以下に示すように。

<div class="col-md-10 bg-dark text-light">
  <% if @single_room %>
    <h4 class="text-center"> <%= @single_room.name %> </h4>
  <% end %>
</div>

ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する 複数の部屋への移動を示す画像

次に、もっとジューシーなメッセージ、メッセージングに移ります。チャットセクションの高さを100vhにして、ページ全体に表示し、メッセージ作成用のチャットボックスを含める必要があります。チャットボックスにはメッセージモデルが必要です。メッセージは作成者とそれが意図された部屋なしでは存在できないため、このモデルにはユーザー参照と部屋参照があります。

rails g model Message user:references room:references content:text
rails db:migrate

また、ユーザーモデルと部屋モデルに次の行を追加して、この関連付けを特定する必要があります。

has_many :messages

メッセージ作成用のフォームをページに追加して、スタイルを追加しましょう:

#app/views/layouts/_new_message_form.html.erb
<div class="form-group msg-form">
  <%= form_with(model: [@single_room ,@message], remote: true, class: "d-flex" ) do |f| %>
    <%= f.text_field :content, id: 'chat-text', class: "form-control msg-content", autocomplete: 'off' %>
    <%= f.submit data: { disable_with: false }, class: "btn btn-primary" %>
  <% end %>
</div>
#app/assets/stylesheets/rooms.scss
  .msg-form {
    position: fixed;
    bottom: 0;
    width: 90%
  }

  .col-md-10 {
    height: 100vh;
    overflow: scroll;
  }

  .msg-content {
    width: 80%;
    margin-right: 5px;
  }

このフォームには@messageが含まれています 変数;したがって、コントローラーで定義する必要があります。これをRoomsControllerのshowメソッドに追加します。

@message = Message.new

routes.rbで ファイルの場合、部屋のリソース内にメッセージリソースを追加します。これは、メッセージの作成元である部屋のIDであるparamsに添付されます。

resources :rooms do
  resources :messages
end

新しいメッセージが作成されるたびに、それが作成された部屋にブロードキャストされるようにします。これを行うには、メッセージをレンダリングする部分的なメッセージが必要です。これが放送されるものなので、turbo_streamも必要です その特定の部屋のブロードキャストメッセージと、これらのメッセージを追加するためのコンテナとして機能するdivを受信します。このコンテナのIDは、ブロードキャストのターゲットと同じである必要があることを忘れないでください。

これをメッセージモデルに追加します:

#app/models/message.rb
after_create_commit { broadcast_append_to self.room }

このようにして、作成された特定の部屋にブロードキャストします。

また、ストリーム、メッセージコンテナ、メッセージフォームをインデックスファイルに追加します。

#within the @single_room condition in app/views/rooms/index.html.erb
<%= turbo_stream_from @single_room %>
<div id="messages">
</div>
<%= render partial: 'layouts/new_message_form' >

ブロードキャストされるメッセージパーシャルを作成し、その中に、部屋が公共のものである場合にのみ送信者のユーザー名を表示します。

#app/views/messages/_message.html.erb
<div>
  <% unless message.room.is_private %>
    <h6 class="name"> <%= message.user.username %> </h6>
  <% end %>
  <%= message.content %>
</div>

コンソールからメッセージを作成すると、割り当てられたテンプレートを使用してその部屋にメッセージがブロードキャストされていることがわかります。

ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する

ダッシュボードからのメッセージ作成を有効にするには、createメソッドをMessagesControllerに追加する必要があります。

#app/controllers/messages_controller.rb
class MessagesController < ApplicationController
  def create
    @current_user = current_user
    @message = @current_user.messages.create(content: msg_params[:content], room_id: params[:room_id])
  end

  private

  def msg_params
    params.require(:message).permit(:content)
  end
end

これが私たちが得るものです: ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する

上のビデオでわかるように、メッセージは追加されていますが、別のチャットルームに移動すると、戻ったときに前のチャットルームのメッセージが失われたように見えます。これは、表示用の部屋に属するメッセージをフェッチしていないためです。これを行うには、RoomsController showメソッドで、部屋に属するすべてのメッセージをフェッチする変数を追加し、インデックスページで、フェッチされたメッセージをレンダリングします。また、メッセージの送信後にメッセージフォームがクリアされないこともわかります。これは、今後の刺激で処理されます。

#in the show method of app/controllers/rooms_controller.rb
@messages = @single_room.messages
#within the div with id of 'messages'
  <%= render @messages %>

これで、各部屋の入り口にメッセージが読み込まれます。

現在のユーザーのメッセージを右に、他のユーザーのメッセージを左に揃えて、これをより見やすくする必要があります。これを実現する最も簡単な方法は、条件message.user == current_userに基づいてクラスを割り当てることです。 、ただし、ローカル変数はストリームで使用できません。したがって、ブロードキャストされたメッセージの場合、current_userはありません。 。私たちは何ができる?メッセージ送信者IDに基づいてメッセージコンテナにクラスを割り当ててから、current_userを利用できます。 application.html.erbにスタイルを追加するためのヘルパーメソッド ファイル。このように、現在のユーザーのIDが2の場合、application.html.erbのスタイルタグのクラス .msg-2になります 、これは、メッセージの送信者が現在のユーザーである場合、メッセージの部分的なクラスにも対応します。

#app/views/messages/_message.html.erb
<div class="cont-<%= message.user.id %>">
  <div class="message-box msg-<%= message.user.id %> " >
    <% unless message.room.is_private %>
      <h6 class="name"> <%= message.user.username %> </h6>
    <% end %>
  <%= message.content %>
  </div>
</div>

message-boxを追加します スタイリング:

#app/assets/stylesheets/rooms.scss
.message-box {
  width: fit-content;
  max-width: 40%;
  padding: 5px;
  border-radius: 10px;
  margin-bottom: 10px;
  background-color: #555555 ;
  padding: 10px
}

application.html.erbのヘッドタグ内 ファイル。

#app/views/layouts/application.html.erb
<style>
  <%= ".msg-#{current_user&.id}" %> {
  background-color: #007bff !important;
  padding: 10px;
  }
  <%= ".cont-#{current_user&.id}" %> {
  display: flex;
  justify-content: flex-end
  }
</style>

!importantを追加します background-colorにタグを付ける 現在のユーザーの背景色を上書きしたいからです。

チャットは次のようになります。 ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する

プライベートチャット

プライベートチャットに必要な作業のほとんどは、グループチャットのセットアップ中に行われました。今やらなければならないことは次のとおりです。

  • 特定のユーザーにルーティングするときに、そのような部屋が存在しない場合は、プライベートチャット用の個室を作成します。
  • そのような部屋の参加者を作成して、侵入者がコンソールからでもそのような部屋にメッセージを送信できないようにします。
  • 新しく作成された個室がルームリストにブロードキャストされないようにします。
  • プライベートチャットの場合は、部屋の名前ではなくユーザーの名前を表示します。

特定のユーザーにルーティングする際、現在のユーザーは、そのユーザーとプライベートにチャットしたいことを示しています。したがって、UsersController 、この2つの間にそのような個室が存在するかどうかを確認します。もしそうなら、それは私たちの@single_roomになります 変数;それ以外の場合は、作成します。プライベートチャットルームごとに特別な部屋名を作成し、必要なときに参照できるようにします。また、同じページにとどまるには、showメソッドにインデックスページに必要なすべての変数を含める必要があります。

#app/controllers/users_controller.rb
class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    @current_user = current_user
    @rooms = Room.public_rooms
    @users = User.all_except(@current_user)
    @room = Room.new
    @message = Message.new
    @room_name = get_name(@user, @current_user)
    @single_room = Room.where(name: @room_name).first || Room.create_private_room([@user, @current_user], @room_name)
    @messages = @single_room.messages

    render "rooms/index"
  end

  private
  def get_name(user1, user2)
    users = [user1, user2].sort
    "private_#{users[0].id}_#{users[1].id}"
  end
end

上記のように、create_private_roomを追加する必要があります 個室とその参加者を作成するRoomモデルのメソッド。これにより、Participantという新しいモデルを作成できます。 、ユーザーとそのユーザーが所属する個室を示します。

rails g model Participant user:references room:references
rails db:migrate

部屋モデルでは、create_private_roomを追加します メソッドを変更し、after_createを変更します 個室でない場合にのみ、部屋の名前をブロードキャストするように呼び出します。

#app/models/room.rb
has_many :participants, dependent: :destroy
after_create_commit { broadcast_if_public }

def broadcast_if_public
  broadcast_append_to "rooms" unless self.is_private
end

def self.create_private_room(users, room_name)
  single_room = Room.create(name: room_name, is_private: true)
  users.each do |user|
    Participant.create(user_id: user.id, room_id: single_room.id )
  end
  single_room
end

他のユーザーが参加者でないときに個室にメッセージを送信できないようにするために、before_createを追加します メッセージモデルを確認してください。したがって、個室の場合、そのようなメッセージが作成される前に、メッセージの送信者が実際にそのプライベート会話の参加者であることが確認されます。ダッシュボードから、参加者でない場合は、ユーザー名をクリックするだけで両方のユーザー用に部屋が作成されるため、個室にメッセージを送信することはできません。このチェックは、参加者以外のユーザーがコンソールからメッセージを作成できるため、セキュリティを強化するためのものです。

#app/models/message.rb
before_create :confirm_participant

def confirm_participant
  if self.room.is_private
    is_participant = Participant.where(user_id: self.user.id, room_id: self.room.id).first
    throw :abort unless is_participant
  end
end

プライベートチャット中に部屋の名前の代わりにユーザーのユーザー名を表示するために、インデックスページに@user 変数が存在する場合、ユーザーのユーザー名が表示されます。この変数は、UsersControllershowメソッドにのみ存在することに注意してください。これにより、部屋名を示すh4タグが次のように変更されます:

<h4 class="text-center"> <%= @user&.username || @single_room.name %> </h4>

これで、ユーザーに移動すると、部屋の名前ではなくユーザーのユーザー名が表示され、メッセージを送受信できます。サインアウトリンクをホームページに追加することを忘れないでください。

<%= link_to 'Sign Out', signout_path,  :method => :delete %>

以下に示すように、プライベートチャットの場合、送信者のユーザー名は表示されません。私たちは自分のメッセージをその位置によって識別することができます。

ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する

刺激

フルページの再レンダリングは行われず、新しいモデルインスタンスの作成時にフォームがクリアされないため、スティミュラスを使用してフォームをクリアします。

bundle add stimulus-rails
rails stimulus:install

これにより、次の画像に示すように、次のファイルが追加されます。 ActionCableとTurboを使用してRailsでリアルタイムチャットアプリを構築する

reset_form_controller.jsを作成します ファイルを作成してフォームをリセットし、次の関数を追加します。

//app/javascript/controllers/reset_form_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  reset() {
    this.element.reset()
  }
}

次に、フォームにデータ属性を追加して、コントローラーとアクションを示します。

data: { controller: "reset-form", action: "turbo:submit-end->reset-form#reset" }

たとえば、form_with メッセージフォームのタグが次のように変更されます:

<%= form_with(model: [@single_room ,@message], remote: true, class: "d-flex",
     data: { controller: "reset-form", action: "turbo:submit-end->reset-form#reset" }) do |f| %>

最後に、必要なのはこれだけです。新しいメッセージまたは部屋を作成すると、フォームがクリアされます。また、刺激アクション"ajax:success->reset-form#reset"にも注意する必要があります。 ajax:successのときにフォームをクリアすることもできます イベントが発生します。

結論

このアプリでは、Turbo Streamsの追加アクションに焦点を当てていますが、TurboStreamsに必要なのはこれだけではありません。実際、Turbo Streamsは、追加、追加、置換、更新、削除の5つのアクションで構成されています。チャットメッセージの削除と更新をリアルタイムで実装するには、これらのアクションが役立ち、Turboフレームとその動作についての知識が必要になる場合があります。また、特定のWebSocket更新に依存するアプリケーションの場合は注意が必要です。機能、接続不良、またはサーバーの問題がある場合、WebSocketが切断される可能性があります。したがって、非常に重要な場合にのみ、アプリでTurboStreamsを使用することをお勧めします。


  1. React on Rails:シンプルなアプリの構築

    アプリケーションのフロントエンド側全体を構築する企業は、多くの場合、バックエンドを構築するためにRailsなどの同じフレームワークを選択します。長年にわたり、これは最良かつ最も信頼できるオプションでした。 今日、絶えず進化するフロントエンドユニバースにある多数のライブラリとフレームワークにより、開発者はバックエンドとフロントエンドの両方に異なるプラットフォームを選択し、それらを簡単に統合できます。 Reactはフロントエンドのパンゲアの巨人になりました。 Ruby on Railsを使用している場合は、デフォルトのRailsページをReactコード(またはその他のフロントフレームワーク)に

  2. Rails5でのAngularの使用

    あなたは前にその話を聞いたことがあります。分散型で完全に機能するバックエンドAPIと、通常のツールセットで作成されたフロントエンドで実行されているアプリケーションがすでにあります。 次に、Angularに移動します。または、AngularをRailsプロジェクトと統合する方法を探しているだけかもしれません。これは、この方法を好むためです。私たちはあなたを責めません。 このようなアプローチを使用すると、両方の世界を活用して、たとえばRailsとAngularのどちらの機能を使用してフォーマットするかを決定できます。 構築するもの 心配する必要はありません。このチュートリアルは、この目的のた