socket.ioとRailwayJSでモデルとsocketを対応させる
やりたいこととしては
・chats/1
・chats/2
などのshowのアクションに対して、オブジェクトとsocketを一対一対応させたい。
だからchats/1でのAさん、Bさんの会話はchats/2のCさん、Dさんの会話とは区別され、Aさんの発言をbroadcastしてもBさんにしか見えないようにしたい。
Room機能を使う
https://github.com/Jxck/socket.io/wiki/Rooms
socket.ioのroom機能を使う。これによって区別する。
どうやって分けるか?
当初、app.jsに書くべきコードをcontroller/showのアクションに書けば解決するのではないかと思った。つまりshowアクションの中で
socket.join(params.id)のようにするということ。
しかし、この方法ではうまくいかなかった。
どういうふうにうまくいかなかったか説明するのが難しい。通ることは通るのだが挙動が少し変だったり、サーバログを見るとconnectionが増大しているようだった。
おそらく、簡単に言うとsocketのサーバサイドの設定はあくまでのイベントの登録なので全アプリ中で起動時に一度呼べばよく、これをリクエストのたびに呼ぶとイベントがどんどん登録されていく、ということだと思う。
config/initializer/socket.coffee
app.io = require('socket.io').listen(app) app.io.sockets.on 'connection', (socket)-> socket.on "enterChat",(chatid)-> socket.join chatid socket.set 'chatid', chatid socket.on "disconnect", -> socket.get 'chatid',(err,chatid)-> socket.leave(chatid)
public/javascripts/client.js
// TRANSFER TRANSCEIVER.enterChat = function(){ id = location.href.split("/").pop(); socket.emit("enterChat",id); };
このように、サーバ側でsocketを切り替えるのではなく、一度chat画面に遷移したのちにそのURLをクライアント側から送ってやって、roomを切り替えることとした。もちろんlocation.href.split("/").pop()の部分はアテで、必ずmongoのidであることをvalidateしないといけない。