Railsを1年くらい触っているのに、ActionCableを触ったことがなかったので、適当な掲示板的なアプリを作りながらActionCableに触ってみました.
Action Cableとは
RailsにWebSocketの仕組みを簡単に導入できるようにしてくれるフレームワーク
WebSocketとは
双方向のプロトコルでリアルタイムの通信が可能で、Ajaxの代わりになるかと言われている技術
環境構築
rubyは2.6.5
、Railsは6.0.3.1
、PostgresSQLは12.3
を使って作ります.
➜ ~ rails -v Rails 6.0.3.1 ➜ ~ ruby -v ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19] ➜ ~ psql --version psql (PostgreSQL) 12.3
$ rails new chat_app_sample -d postgresql $ rails db:create $ rails s
http://localhost:3000 にアクセスしてYay! You’re on Rails!が表示されることを確認出来ました.
Action Cableを使わずにメッセージの作成機能と一覧表示機能を実装する
Message modelを作成します.
$ rails g model Message body:string $ rails db:migrate
messages controllerを作成します
$ rails g controller messages index create
routingを整理します.
Rails.application.routes.draw do root to: "messages#index" resources :messages, only: [:create, :index] end
messages controllerを実装していきます.
class MessagesController < ApplicationController def index @message = Message.new @messages = Message.all enddef create @message = Message.new(message_params) if @message.save redirect_to messages_path end end
private
def message_params params.require(:message).permit(:body) end end
Viewを編集していきます.
<h1>Messages#index</h1> <ul id="messages_list"> <%= render @messages %> </ul><%= form_with(model: @message, local: true) do |f| %> <%= f.label :body, "内容" %> <%= f.text_field :body %> <%= f.submit %> <% end %> </div>
<li><%= message.body %></li>
以上の実装でメッセージの作成の成功時、リダイレクトされて画面が更新されてメッセージ一覧が表示されるところまで実装できました.
Action Cableを導入してみる
Channelを作成し、cableをmountさせます.
$ rails g channel message
Rails.application.routes.draw do root to: "messages#index" resources :messages, only: [:create, :index] mount ActionCable.server, at: '/cable' #追加 end
subscribed
メソッドでmessage_channel
をストリーミングさせます.
class MessageChannel < ApplicationCable::Channel def subscribed stream_from "message_channel" enddef unsubscribed # Any cleanup needed when channel is unsubscribed end end
ログでchannelをストリームされていることが確認できました.
ストリームされていることを確認できたので、Messageが作成されたらブロードキャストされるようにmessages#create
を修正します.
・ ・ def create message = Message.new(message_params) if message.save ActionCable.server.broadcast "message_channel", message: message.body end end
app/javascript/channels/message_channel.js
でブロードキャストされた時の処理を書きます.
import consumer from "./consumer";consumer.subscriptions.create("MessageChannel", { 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) {
// データを操作する const list = document.createElement('li'); list.textContent = data.message; const lists = document.getElementById('messages_list'); lists.append(list); //残ったテキストフィールドを空にする document.getElementById('message_body').value = ''; }, });
動作確認
リアルタイムで動くことが確認できました.😀