pusherの助けを借りたWebSocketを使ったチャットシステム
リアルタイムなchatを作りたい。
そんな欲求誰にでもあるものです。
時間のない主婦の方にも手軽にパパっとチャットシステムを作る方法を紹介しようと思います。
材料は
rails
pusher
作る料理は
チャットシステム(現在の参加者表示機能付き)
の二つです。
変なテンションな書き方はここまで。
今日の記事は全面的にここを参考にさせていだきました。
Yuno
pusherはWebSocketsを利用したAPIです。
Leader in realtime technologies| Pusher
わかりやすい図はっときます。
例えばブラウザがpostリクエスト投げると、それを受け取ったサーバからpusherにそのデータを加工してパス。
するとブラウザにpushしてくれるというイメージ。
pusher利用にはユーザ登録で得られるAPI Credentialsが必要です。
まずはpusherのサイトでユーザ登録して、
app _id
key
secret
をゲットしてください。
今日の記事は実際に作ったものからコピペで書いていますが。
view部分はhamlで書いてるので、見ずらくてすいません。
erbメインの方は脳内で変換かけてください。
とりあえずGemfileに記述
bundle install後、config/initializers内にpusher.rb作成
1
2
3
| Pusher.app_id = ユーザ登録でゲットしたapp_id
Pusher.key = ユーザ登録でゲットしたkey
Pusher.secret = ユーザ登録でゲットしたsecret
|
config/route.rbにauthアクションへのルーティング追加
1
2
3
| resources :chats , :only => [:index , :create , :destroy] do
post :auth , :on => :collection
end
|
現在の参加者を取得するためには、pusherのPresence
Channelsを使用しなければなりません。
Presence
Channelsを使用するためには、認証を受けること・channel名のprefixにpresence-つけないといけません。
view
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| = javascript_include_tag "http://js.pusher.com/1.11/pusher.min.js"
:javascript
$(function(){
Pusher.channel_auth_endpoint = '/chats/auth';
var pusher = new Pusher("#{ユーザ登録でゲットしたkey }");
var channel = pusher.subscribe("presence-chat");
channel.bind("chatevent", function(html) {
$("#chat_body").val('');
$("ul").prepend(html);
});
channel.bind('pusher:subscription_succeeded', function(members){
members.each(add_member);
});
channel.bind('pusher:member_added', function(member){
add_member(member);
})
channel.bind('pusher:member_removed', function(member){
remove_member(member);
})
});
function add_member(member) {
var container = $("<span>", {
"class": "member",
id: "presence_" + member.id
});
$('.members').append(container.html(member.info.name + " "))
}
function remove_member(member) {
$('#presence_' + member.id).remove();
}
= render "form"
%div
現在の参加者
%span.members
%ul#chat_list
= render partial: "list", locals: { :chats => @chats }
|
フォームとリストの部分テンプレートは割愛。
認証は
1
| Pusher.channel_auth_endpoint = '/chats/auth';
|
で指定したエンドポイントにコールバックされます。
controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| class ChatsController < ApplicationController
protect_from_forgery :except => :auth
def create
@new_post = Chat.new(params[:chat])
@new_post.user = @current_user
if @new_post.save
Pusher["presence-chat"].trigger!(
"chatevent",
render_to_string(
file: "chats/_list.html.haml",
layout: false,
locals: { :chats => Array.wrap(@new_post) }
)
)
end
render 'index'
end
def auth
if current_user
auth = Pusher["presence-chat"].authenticate(params[:socket_id],{
:user_id => @current_user.id,
:user_info => {
:name => @current_user.name
}
}
)
render :json => auth
else
render :text => "Not authorized", :status => '403'
end
end
end
|
endpointで設定したauthアクションでは、コールバックされた際に渡されるsocket _idを引数authenticateを実行しています。
ちなみに自分はこの認証ではまりました。
1
| protect_from_forgery :except => :auth
|
でコールバックで呼び出された際に、CSRFを無効にしてあげる必要があったんですねぇ。
以上で多分動くはずです。