こんにちわ エンジニアのMariMurotaniです。
社内のアイデアソン/ハッカソンイベントで利用するために、 Action Cableの機能を使って「いいね!」ボタンを作成しました。 websocker-railsを利用します。 社内のWD(ディレクターかつデザイナー)が10分で作ってくれた画像を使って1時間で開発しました。
最終更新日時がApr 2016と大分更新されていないのでちょうど出たときに話題になっただけのようなのでWebSocketの本格的な利用を考えると今後はAPI Gatewayなどを利用してみるといいかもしれません。 aws.amazon.com
1. gemの追加
gem 'websocket-rails'
bundle installします
2. 初期化
rails g websocket_rails:install
3. 設定
config/environments/development.rbに下記の行を追加します
Rails.application.configure do ..... config.middleware.delete Rack::Lock ..... end
3. ビューとモデルの作成
まずは普通にcontrollerとviewを作成しておきます
rails generate model Counter count:integer rails generate controller home bin/rake db:migrate
/config/routes.rbの設定をします
root 'home#index' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html root to:'application#home' end
HomeControllerの中身はこんな感じにしておきましょう。
class HomeController < ApplicationController def index counter = Counter.last @count = counter.count end end
HomeControllerの中身はこんな感じにしておきましょう 次にSubscribe用のチャンネルを作成します
rails g channel room speak vote
app/channels/room_channel.rbを書き換えます
class RoomChannel < ApplicationCable::Channel def subscribed stream_from "room_channel" end def unsubscribed # Any cleanup needed when channel is unsubscribed end def speak(data) ActionCable.server.broadcast 'room_channel', message: data['message'] end def vote counter = Counter.last.presence || Counter.new counter.attributes = {count: counter.count+1} counter.save! @count = counter.count ActionCable.server.broadcast 'room_channel', message: @count system('afplay /System/Library/Sounds/Submarine.aiff') end end
app/assets/javascripts/channels/room.coffeeを書き換えます
App.room = App.cable.subscriptions.create "RoomChannel", connected: -> # Called when the subscription is ready for use on the server #console.log("subscribe start") disconnected: -> # Called when the subscription has been terminated by the server received: (data) -> # Called when tconsole.log(data) # here's incoming data on the websocket for this channel $("#msg_box").html(data["message"].toString()) speak: (message)-> @perform 'speak', message vote: -> @perform 'vote'
app/view/home/index.html.erbを書き換えます
<div class="main_content"> <div> <span class="card-number" id="msg_box"><%= @count %></span> </div> <a id="iine_button" class="button" ></a> </div> <!-- Compiled and minified CSS --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"> <script> jQuery(document).ready(function(){ $("#iine_button").on('click',function(){ App.room.vote(); }); }); </script>
4. サーバー起動とテスト
bin/rails server -b 0.0.0.0 -p 4649
でサーバを立ち上げます
今回はvoteとspeakの関数を作ったのでコンソールから両方呼び出ししてみましょう
ボタンについているアクションはvoteの方だけなのでVoteを押すと画面の数値が繰り上がります
複数の端末で接続した際にActionCable.server.broadcast
を通して接続した端末すべてに変更の通知が飛びます
これがWebSocketを利用したリアルタイム更新のユースケースです
サーバーログを確認すると/cableのエイリアスが自動で処理をしてくれているのが確認できます WebSocketの機能をRails内に隠蔽したもので手間がかからずデモなんかを作れるのでこういったgemのアイデアっていいなと思いました