2016-10-01 20 views
3

私はアクションケーブルと苦労しています。私の場合、私は(Devise経由で)お互いにタスクを共有できる2人のユーザーがいます。レールアクションケーブル特定の消費者

が(フォーム経由で)user#2でタスクを共有すると、すべての認証済みユーザーが通知を受け取ります。

user#2はどのようにして自分にブロードキャストする必要がありますか?ここで

は、これまでの私のコードです:

connection.rb

module ApplicationCable 
    class Connection < ActionCable::Connection::Base 
    identified_by :current_user 

    def connect 
     self.current_user = find_verified_user 
     logger.add_tags 'ActionCable', current_user.id 
    end 

    protected 

    def find_verified_user # this checks whether a user is authenticated with devise 
     if verified_user = env['warden'].user 
     verified_user 
     else 
     reject_unauthorized_connection 
     end 
    end 
    end 
end 

cable.js

(function() { 
    this.App || (this.App = {}); 

    App.cable = ActionCable.createConsumer(); 

}).call(this); 

todo_channel.rb

class TodoChannel < ApplicationCable::Channel 
    def subscribed 
    stream_from "todo_channel_#{current_user.id}" 
    end 

    def unsubscribed 
    # Any cleanup needed when channel is unsubscribed 
    end 


    def notify 
    ActionCable.server.broadcast "todo_channel_#{current_user.id}", message: 'some message'(not implemented yet) 
    end 
end 

私はあなたが実際にチャンネルにstream_fromを複数回呼び出すことができますし、そのユーザが複数の異なる「部屋」に加入されることを実現するまで私が前に似た何かを直面してきました

App.todo = App.cable.subscriptions.create "TodoChannel", 
    connected: -> 
    # Called when the subscription is ready for use on the server 

    disconnected: -> 
    # Called when the subscription has been terminated by the server 

    received: (data) -> 
    console.log(data['message']) 

    notify: -> 
    @perform 'notify' 

答えて

3

私は別のアプローチで終わりました。もし誰かがそれが役に立つと思ったら、私はここに書きます。

通知には、通知するユーザーのIDがあります。だから、モデルに私が持っている:

after_commit :broadcast_notification, on: :create 

def broadcast_notification 
    ActionCable.server.broadcast "todo_channel_#{self.user_id}", message: 'some message' 
end 

私がモデルに放送を置いたように私todo_channel.rbは次のようになります。

class TodoChannel < ApplicationCable::Channel 
    def subscribed 
    stream_from "todo_channel_#{current_user.id}" 
    end 

    def unsubscribed 
    # Any cleanup needed when channel is unsubscribed 
    end 
end 
+0

この 'todo_channel.rb'コードは、' app/channels/application_cable/connection.rb'が 'current_user'を提供するように設定されている場合にのみ機能します。実際、これにはセキュリティを含む例があります(https://github.com/rails/rails/tree/master/actioncable#examples) – brod

5

todo.coffee同じチャネル接続内にある。どちらがあなたは基本的にユーザーがすでに他のユーザーのIDを知っていると仮定して、この

class TodoChannel < ApplicationCable::Channel 
    def subscribed 
    stream_from "todo_channel_all"        
    stream_from "todo_channel_#{current_user.id}" 
    end 

    def unsubscribed 
    # Any cleanup needed when channel is unsubscribed 
    end 

    def notify(data) 
    # depending on data given from the user, send it to only one specific user or everyone listening to the "todo_channel_all" 
    if data['message']['other_user_id'] 
     ActionCable.server.broadcast "todo_channel_#{data['message']['other_user_id']}", message: 'some message' 
    else 
     ActionCable.server.broadcast "todo_channel_all", message: 'some message' 
    end 

    end 
end 

そのコードを実行することができることを意味し、チャネルにそれを送った、あなたはおそらく、いくつかのセキュリティか何かで、私は」を認めることをラップする必要があります私はまだ学んでいるように、レールで十分に経験はありません。

将来あなたにとって有益なことは、同じチャネル機能で複数のメッセージ/時間をブロードキャストできるということです。つまり、特定の単一のユーザー、特定のユーザーまたは全員のリストにタスクを送信することを潜在的にサポートできます。ユーザーのリスト/配列/何でも繰り返すだけで、自分の個人的な "todo_channel _#{user.id}"でタスク/メッセージ/通知/何でも自分のものをブロードキャストします。

1

ステップ#1:各ユーザーが独自のセッショントークンを持ってみましょう。サブスクリプション中、各ユーザーはヘッダーでセッショントークンを送信し、ヘッダーは接続クラスでアクセス可能です。セッショントークンを使用してユーザーを検索します。

ステップ2:ユーザーIDでユーザーをストリームします。

ステップ3:タスクを共有している間に、要求でユーザーIDも取得し、指定されたユーザーIDでブロードキャストします。

1

これは「プライベートチャット」と呼ばれます。 todo.coffeeからサーバーへ

  1. いくつかのAJAX onloadコール:あなたは本当にcurrent_user.idを取得したい場合は、3通りの方法でそれを行うことができます。

  2. で、ユーザログながら、プレーンクッキーを作成し、todo.coffee

  3. の内側にそれを確認( https://www.sitepoint.com/create-a-chat-app-with-rails-5-actioncable-and-devise/のように)

  4. をRailsのHTMLビューの属性としてcurrent_user.idをレンダリングしてからtodo.coffee内のjQueryを経由してそれを得ます

current_user.idは安全ではないため使用しないでください。あなたがそれを使用する場合、誰かが同じサイトに登録し、単にランダムuser_idを提供するだけで、他のユーザーのプライベートチャットを簡単に聞くことができます。

代わりに、署名付き(例:Railsで暗号化された)Cookieをユーザーの一意のブロードキャスト識別子として使用します。そうすれば、同じサイトに登録すると、他のユーザーの署名付きCookieを知ることができなくなります。そのため、外国人のプライベートチャットに侵入することはできません。

アプリ/設定/初期化子/ warden_hooks.rb

https://rubytutorial.io/actioncable-devise-authentication/

# Be sure to restart your server when you modify this file. 

Warden::Manager.after_set_user do |user,auth,opts| 
    scope = opts[:scope] 
    auth.cookies.signed["#{scope}.id"] = user.id 
end 

Warden::Manager.before_logout do |user, auth, opts| 
    scope = opts[:scope] 
    auth.cookies.delete("#{scope}.id") 
end 

todo_channel.rb

class TodoChannel < ApplicationCable::Channel 
    def subscribed 
    stream_from "todo_channel_#{params['user_signed_cookie']}" 
    end 

    def unsubscribed 
    # Any cleanup needed when channel is unsubscribed 
    end 


    def notify(param_message) 
    ActionCable.server.broadcast "todo_channel_#{param_message['user_signed_cookie']}", message: 'some message'(not implemented yet) 
    end 
end 

todo.coffee

を参照してください。
user_signed_cookie = document.cookie.replace(/(?:(?:^|.*;\s*)user.id\s*\=\s*([^;]*).*$)|^.*$/, "$1"); 

user_logged_in = if user_signed_cookie then true else false 

if user_logged_in #avoid repetitive HTTP->WebSockets upgrade pointless browser attempts when no user logged in. 
App.todo = App.cable.subscriptions.create { 
      channel:"TodoChannel" 
      user_signed_cookie: user_signed_cookie 
     }, 
    connected: -> 
    # Called when the subscription is ready for use on the server 

    disconnected: -> 
    # Called when the subscription has been terminated by the server 

    received: (data) -> 
    console.log(data['message']) 

    notify: (name, content, _) -> #name, content - message fields 
    @perform 'notify', name: name, content: content, user_signed_cookie: user_signed_cookie 
関連する問題