JQueryは古いテクノロジーとはいえ、さくっと動くものを作るときは異常に簡単です。 古いテクノロジーは悪ではなく適材適所で使っていくのが大事だと思っています。
まずは、最初からあるapp/assets/javascripts/cable.js
を該当layoutで読み込みます。
# app/assets/javascripts/application.js ... //= require cable.js
全部のViewでApp.cableを呼ぶ必要はないのでcontent_for
でActionCableとの通信をとるViewだけJSを走らせるようにします。
#app/views/layouts/application.html.erb <head> ... <%= yield :page_scripts %> </head>
JSでは、App.cableにイベントを登録していきます。 引数のchannelにはクラス名、引数を渡すとparamsに入ってサーバ側で処理できます。this.perform
を使ってクラス内のメソッドを呼ぶことができます。development環境では別プロセスで動作確認ができないのでsetTimeoutを用いてテストしています。
<% content_for :page_scripts do %> <script> $(function(){ // Subscrubung host status $('span.host-status') .filter(function(i){ return $(this).text() !== "terminated"; }) .each(function(i){ var hostId = $(this).data('hostId'); var self = this; App.cable.subscriptions.create({channel: "HostStatusChannel", host_id: hostId}, { connected: function(){ console.log('connected'); //var self = this; //setTimeout(function(){ // console.log('say now'); // self.perform("say"); //}, 1000); }, received: function (data) { var currentStatus = $(self).text(); if(data.status !== currentStatus){ $(self).fadeOut(500, function(){ $(self).text(data.status); $(self).fadeIn(); }); } }, }); }); }); </script> <% end %>
HTML部分は下記のような感じ。
<span class="host-status" data-host-id="<%= host.id %>"><%= host.status %></span>
で最後になりますが、ActionCableを継承したクラスです。subscribedがconnectionとともに走ります。 stream_for MODEL
でモデルに関係したチャネルが接続されます。 そして、broadcast_to(MODEL, object)でそのモデルへの接続を確率したチャネルにプッシュすることができます。
# app/channels/host_status_channel.rb class HostStatusChannel < ApplicationCable::Channel def subscribed host = Host.find(params[:host_id]) stream_for host end def say # for testing HostStatusChannel.broadcast_to(Host.find(1), "hi") end end
これでダイナミックにDOMを操作できるようになりました。