websocket-railsで特定ユーザにメッセージを送信する †準備 †websocket-railsインストール を参照して環境構築 サーバ処理の作成 †WebSocketイベント定義 †config/events.rb subscribe :notify_user , 'messages#notify_user' WebScoketコントローラ作成 †app/controller/messages_controller.rb class MessagesController < WebsocketRails::BaseController
def notify_user
logger.debug("notify_user!");
# 未ログイン時は何もしない
if !current_user
return
end
uid = message[:uid]
from_uid = current_user.id
from_user = User.find(from_uid)
from_email = from_user[:email]
result = false
#if WebsocketRails.users[uid] # これだとWebsocketサーバが落ちる ※1
if WebsocketRails.users.users[uid]
if WebsocketRails.users[uid].connected?
WebsocketRails.users[uid].send_message('notification', { :msg => message[:msg], :from => from_email , :type => "user" })
result = true
end
end
# 結果通知
if result
logger.debug("notify OK!");
trigger_success({ :msg => "send OK!"})
else
logger.debug("notify error!");
trigger_failure({ :error => "error!"})
end
end
.
.
end
※1 ... find_remote_user から呼ばれている WebsocketRails.synchronize? , Synchronization.find_user(identifier) , remote_connection のどれかだと思うが詳しくは見ていない。 共通処理(js)の作成 †app/assets/javascript/_common.js jQuery(function($){
var myapp = window.myapp = window.myapp || {};
/**
* websocket接続処理
*/
myapp.wsConnected = false;
myapp.wsConnect = function(){
if (myapp.wsConnected) {
return;
}
myapp.dispatcher = new WebSocketRails(location.hostname + ":3001/websocket");
if (myapp.dispatcher) {
myapp.wsConnected = true;
console.log("ws connect!");
myapp.dispatcher.bind('connection_closed', function() {
console.log("ws close!");
myapp.wsConnected = false;
myapp.wsConnect();
});
} else {
console.log("ws connect error!");
}
};
/**
* 全体通知のsubscribe
*/
myapp.subscribed = {};
myapp.subscribe_default = function(event_name){
event_name = event_name || "notification";
if (myapp.subscribed[event_name]){
return;
}
myapp.dispatcher.bind(event_name, function(data) {
console.log("websocket receive message");
myapp.showNotifyDialog(data);
});
myapp.subscribed[event_name] = true;
};
});
メッセージ送信用画面の作成 †コントローラの作成 †app/controller/chats_controller.rb class ChatsController < ApplicationController
#
# 全ユーザへのメッセージ送信画面
#
def alls
end
#
# ユーザ一覧を表示する
#
def users
@users = user_list
@uid = params[:uid] || nil
@msg = params[:msg] || nil
if request.post?
to_user
end
end
private
#
# ユーザ一覧を取得する.
#
def user_list
users = []
online_users = []
WebsocketRails.users.each do |conn|
online_users << conn.user[:id]
end
all_users = User.all
all_users.each do |u|
rec = u.attributes.compact!
rec["status"] = online_users.include?(rec["id"])
users << rec
end
users
end
ビューの作成 †app/views/chats/users.html.erb <h3>ユーザを指定してメッセージを送信する</h3>
<%= render :partial => "shared/messages" %>
<%= form_tag('/chats/users', :method => :post, :id => "sendto_user_form") do %>
<div>ユーザ</div>
<table class="tbl">
<thead>
<tr>
<th> </th>
<th>Email</th>
<th>オンライン</th>
</tr>
</thead>
<tbody>
<% @users.each_with_index do |u,i| %>
<tr>
<td><input type="radio" name="uid" value="<%= u["id"] %>" <%= @uid.to_s == u["id"].to_s ? "checked=checked" : "" %> /></td>
<td><%= u["email"] %></td>
<% if current_user[:id].to_s == u["id"].to_s %>
<td>自分</td>
<% else %>
<td><%= u["status"] ? "◯" : "" %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<br />
<div>メッセージ</div>
<div>
<textarea name="msg" rows="5" cols="40"><%= @msg %></textarea>
</div>
<input id="btn_ws" type="button" value="メッセージ送信" />
<% end %>
クライアント処理の作成 †app/assets/javascript/chats/users.js jQuery(function($){
/**
* [websocket送信]
*/
$(document).on("click", "#sendto_user_form #btn_ws", function(e){
var data = { "uid" : $("form").find("[name=uid]:checked").val(), "msg" : $("form").find("[name=msg]").val() };
myapp.dispatcher.trigger("notify_user", data,
function(data){
console.log("送信しました。");
},
function(data){
alert("送信できませんでした。");
}
);
});
// ws接続
myapp.wsConnect();
// subscribe
myapp.subscribe_default();
});
|