Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

Rails 5の目玉機能「Action Cable」で双方向通信を実装(2)

サンプルコードで学ぶRuby on Rails 5実践入門 第8回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2017/07/10 14:00

 前回はRails 5目玉機能の1つであるAction Cableのサンプルアプリ実装を通してAction Cableへの理解を深めました。今回は引き続きAction Cableのサンプルアプリを拡張して、発言をデータベースに保存できるようにし、会員登録機能と関連付けを行います。

目次

発言をデータベースに保存する

 まずは発言をデータベースに保存できるようにします。発言をDB保存するにあたり、まずはサーバー側で発言を保存した後、非同期でクライアント側にブロードキャストするよう修正します。なお、この時点では発言するのにログインは必須としていないので、ユーザーIDをchat_messagesテーブルに保存する処理は入れず、後から処理を加えます。

 修正の手順をまとめると以下の通りです。

  • チャネルからモデルを生成するように修正
  • モデルのデータ保存をチャネル側で行うように修正
  • モデルが保存されてから非同期でブロードキャストするジョブを作成
  • 初期アクセス時に保存した発言が表示されるように修正

チャネルからモデルを生成するように修正

 まず、チャネル内で直接ブロードキャストしていた箇所を、モデルを生成するためspeakメソッドをリスト1の通りに修正します。

リスト1 app/channels/chat_message_channel.rb
class ChatMessageChannel < ApplicationCable::Channel
…(中略)…
  def speak(data)
    ChatMessage.create! body: data['message']
  end
end

 モデルの生成にはcreate!メソッドを使用します。create!メソッドは何らかの理由でレコード生成に失敗した場合に例外を投げるメソッドです。data['message']で受け取った発言をchat_messagesテーブルのbodyカラムにセットしてレコードを生成します。

モデルの修正

 ブロードキャストする処理をモデルが生成した後のタイミングで行うよう、リスト2の通りに修正します。

リスト2 app/models/chat_message.rb
class ChatMessage < ApplicationRecord
  after_create_commit { ChatMessageBroadcastJob.perform_later self }
end

 after_create_commitメソッドは、ActiveRecordのcreateまたはcreate!メソッドが呼び出されてデータベースへのコミットが正常終了した後に、{}で指定したブロックが後処理として呼び出します。ChatMessageBroadcastJobは、次の手順で作成するジョブでperform_laterメソッドを通じて呼び出すことができます。引数にself、つまりモデル自身を渡しています。

非同期でブロードキャストするジョブの作成

 ジョブとは、Rails 4.2から導入された非同期処理の仕組みのことで、Active Jobと呼ばれます。ジョブファイルの生成は、Railsが提供するジェネレーターコマンドを使用します。

bin/rails g job ChatMessageBroadcast

 ↓

Running via Spring preloader in process 83621
      invoke  test_unit
      create    test/jobs/chat_message_broadcast_job_test.rb
      create  app/jobs/chat_message_broadcast_job.rb

 ジェネレーターコマンドで自動生成されたファイルを確認してみましょう。

リスト3 app/jobs/chat_message_broadcast_job.rb
class ChatMessageBroadcastJob < ApplicationJob
  queue_as :default

  def perform(*args)
    # Do something later
  end
end

 queue_asメソッドは、ジョブを実行するキューの名前を指定するものです。呼び出し側でperform_laterメソッドによってジョブが呼び出されると、performメソッドに記述された処理が実行されます。このジョブが実行されたら、ブロードキャストする処理をperformメソッドに記述しましょう。

リスト4 app/jobs/chat_message_broadcast_job.rb
class ChatMessageBroadcastJob < ApplicationJob
…(中略)…
  def perform(chat_message)
    ActionCable.server.broadcast 'chat_message_channel', message: chat_message.body
  end
end

 追加したブロードキャストする処理は、元々チャネルのspeakメソッドで定義していた処理のままです。

初期アクセス時に保存した発言が表示されるように修正

 次に、保存した発言をデータベースから取得して表示されるように修正します。まずはコントローラーをリスト5の通りに修正しましょう。

リスト5 app/controllers/chat_messages_controller.rb
class ChatMessagesController < ApplicationController
  def index
    @chat_messages = ChatMessage.all
  end
end

 ChatMessage.allで全ての発言をchat_messagesテーブルから取得して、インスタンス変数@chat_messagesに代入してビューで使用できるようにします。

 次にビューをリスト6の通りに修正しましょう。

リスト6 app/views/chat_messages/index.html.erb
<div id='chat_messages'>
  <% @chat_messages.each do |chat_message| %>
    <div><%= chat_message.body %></div>
  <% end %>
</div>
…(中略)…

 全ての発言が代入されている@chat_messagesをeachでループして、1つ1つの発言をdiv要素で囲んで表示しています。

動作確認

 これで、一通り発言をデータベースに格納した後にブロードキャストする修正が完了しました。「http://localhost:3000/chat_messages/index」にアクセスして動作確認をしてみましょう。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト 竹馬 力(チクバ ツトム)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2017年5月時点での登録メンバは52名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

バックナンバー

連載:サンプルコードで学ぶRuby on Rails 5実践入門

もっと読む

All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5