8
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Railsを使ってチャットアプリを作る

Last updated at Posted at 2019-11-25

#はじめに
Railsを使って簡単なチャットアプリを作ったので、そのときの手順をまとめました。

chat-app.gif

#環境

$ ruby -v
ruby 2.5.1p57 (2018-03-29 version 63029) [x86_64-darwin19]

$ bin/rails -v
Rails 5.2.3

#参考
チャットアプリを作る際、以下を参考にさせて頂きました。
この記事で掲載しているソースコードの大半は下記の2つのページの内容が基になっています。

Action Cableでリアルタイムチャットアプリの作成方法 (Rails 5.1.4にて)(その1) herokuで動かす!
Rails 5 + ActionCableで作る!シンプルなチャットアプリ(DHH氏のデモ動画より)

#ソースコード
チャットアプリのソースコードは以下で確認できます。
Neufo/rails-sample-app/ChatApp

#手順

1. アプリケーションを作る

まずはチャット機能を実装するアプリケーションを作ります。

$ rails new ChatApp

2. コントローラーを作る

ChatAppディレクトリに移動して以下のコマンドを実行します。

$ bin/rails generate controller rooms show

これでChatApp/app/controllers/rooms_controller.rbが作られます。

3. モデルを作る

ユーザーが入力したメッセージを保存するモデルを作ります。

$ bin/rails generate model message content:text
$ bin/rails db:migrate

4. メッセージの一覧を表示する

RoomsControllerのshowメソッドでメッセージの一覧を取得します。

ChatApp/app/controllers/rooms_controller.rb
class RoomsController < ApplicationController
  def show
    @messages = Message.all
  end
end

取得したメッセージを表示するためにViewを編集します。1

ChatApp/app/views/rooms/show.html.erb
<h1>Chat room</h1>

<div id="messages">
  <%= render @messages %>
</div>

messagesの各要素をページに埋め込むために部分テンプレートを作ります。
(ChatApp/app/views/ に messagesフォルダを作り、その中にファイルを保存します)

ChatApp/app/views/messages/_message.html.erb
<div class="message">
  <p><%= message.content %></p>
</div>

5. チャンネルを作る

クライアント/サーバ間の通信処理のひな形を作ります。

$ bin/rails generate channel room speak

コマンドを実行するとクライアント用、サーバ用のファイルが作られます。

  • ChatApp/app/assets/javascripts/channels/room.coffee (クライアント)
  • ChatApp/app/channels/room_channel.rb (サーバ)

サーバを起動して動作を確認してみます。

$ bin/rails s

ブラウザで/rooms/showを開き、コンソールでApp.room.speak()と入力します。trueが返ってくれば成功です。
スクリーンショット 2019-11-24 22.53.29.png

6. jQueryを有効にする

クライアントがメッセージを送受信するときにjQueryを使うので準備しておきます。

ChatApp/Gemfile
gem 'jquery-rails'

上記をGemfileに追記したらbundle updateを実行します。

jQueryのライブラリを読み込むようapplication.jsに追記します。

ChatApp/app/assets/javascripts/application.js
(省略)
//= require jquery
//= require jquery_ujs
//= require_tree .

7. メッセージの送受信処理を作る

以下の機能を作ります。

  • クライアント側
  • サーバからメッセージを受信する (received)
  • ユーザが入力したメッセージをサーバに送信する (speak)
ChatApp/app/views/rooms/show.html.erb
<form>
  <label>Say something:</label><br>
  <!-- room_speaker からサーバへメッセージを送信する -->
  <input type="text" data-behavior="room_speaker">
</form>
ChatApp/app/assets/javascripts/channels/room.coffee
$(document).on 'keypress', '[data-behavior~=room_speaker]', (event) ->
    # Enterキーが押されたらサーバへメッセージを送信する
    if event.keyCode is 13 # return = send
        App.room.speak event.target.value
        event.target.value = ''
        event.preventDefault()

App.room = App.cable.subscriptions.create "RoomChannel",
  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) ->
    # メッセージ一覧の末尾に受信したメッセージを追加する
    $('#messages').append data['message']

  speak: (message) ->
    # サーバのspeakメソッドを呼び出す
    @perform 'speak', message: message
  • サーバ側
  • room_channelを購読する (subscribed)
  • クライアントから受信したメッセージを保存する (speak)
  • room_channelに参加しているクライアントにメッセージをブロードキャストする (perform)
ChatApp/app/channels/room_channel.rb
class RoomChannel < ApplicationCable::Channel
  def subscribed
    # room_channelからデータを受信する
    stream_from "room_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def speak(data)
    # データベースにクライアントから受信したメッセージを保存する
    Message.create! content: data['message']
  end
end

メッセージをブロードキャストするジョブを定義します。

$ rails generate job MessageBroadcast
ChatApp/app/jobs/message_broadcast_job.rb
class MessageBroadcastJob < ApplicationJob
  queue_as :default

  def perform(message)
    # room_channelにメッセージをブロードキャストする
    ActionCable.server.broadcast 'room_channel', message: render_message(message)
  end

  private
    def render_message(message)
      ApplicationController.renderer.render(partial: 'messages/message', locals: { message: message })
    end
end

データベースにメッセージを保存したら、ジョブを登録します。

ChatApp/app/models/message.rb
class Message < ApplicationRecord
    # データベースにメッセージが保存されたらジョブを登録する
    after_create_commit { MessageBroadcastJob.perform_later self }
end

登録されたジョブは自動的に実行されます。
MessageBroadcastJobのperformメソッドが呼び出され、すべてのクライアントにメッセージが送信されます。
クライアントはreceivedでメッセージを受け取り、メッセージ一覧の末尾に受信したメッセージを追加します。
これでチャットアプリの作成は終了です。

  1. <%= render @messages %><%= render partial: "messages/message", collection: @messages %>を省略形です。参考:コレクションをレンダリングする

8
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?