---
# System prepended metadata

title: 12th 鐵人賽 Day_27 action cable ? (4)
tags: [12th 鐵人賽]

---

---
title: 12th 鐵人賽 Day_27 action cable ? (4)
tags: 12th 鐵人賽
--- 
# 12th 鐵人賽 Day_27 action cable ? (4)

嗨！各位朋友大家好，打給後，歹嘎吼，胎尬喉，我是阿圓，一樣有請今天的one piece：
![](https://i.imgur.com/FtlbWiA.jpg)
(漢考克也是我蠻喜歡的一個角色！)

昨天我們說到 action cable 的基本操作，先幫各位複習一下：

1. action cable 採用 pub/sub (發布/訂閱) 的模式
2. 每一個 client 端，透過訂閱 channel 成為 subscriber
3. server 透過 channel 中的 stream 將訊息廣播(Broadcast)出去

今天繼續來說一些比較進階的設定：

# connection
每當有一次的 websocket 連線，連進server，就會有一個 connection 被創立(而 websocket 的 client 端，Rails 稱之為 consumer)，connection，本身並不包含任何的身份驗證，也就是說，就算你沒有登入，你還是可以連接到 channel ，所以我們可以在 connction 建立時來驗證：
```ruby=
# app/channels/application_cable/connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user
 
    def connect
      self.current_user = find_verified_user
    end
 
    private
      def find_verified_user
        if verified_user = User.find_by(id: cookies.encrypted[:user_id])
          verified_user
        else
          reject_unauthorized_connection
        end
      end
  end
end
```
上述是利用 cookie 的方式去驗證，若自己有訂定義驗證使用者的方式可以拿來用，像 devise 是使用：
```ruby=
    def find_verified_user 
      if verified_user = env['warden'].user
        verified_user
      else
        reject_unauthorized_connection
      end
```


## 一對一的聊天室

昨天提到了如何讓 server 正確廣播，也能讓 subscriber 正確收到訊息，而今天來提提不同型態的聊天室設定。

比較簡單的是一對多的聊天室，也就是大家都在同一個 channel 中，這樣就不用去管不同 stream 的部分。

若是一對一的聊天室，你的stream可能要是某個params中的id，像是：
```ruby=
class RoomsChannel < ApplicationCable::Channel
  def subscribed
    room = Room.find(params[:room_id])
    stream_for room
  end
end
```
上面是依賴 room 這個 model 資料來建立 stream，而不同的 room 就有不同的 stream ，這樣能夠達到一對一的方式


這樣的話，在js檔那邊也要一起做設定：
```javascript=
consumer.subscriptions.create({
    channel: "RoomsChannel",
    room_id: 1
  }, 
  ...
```
等等等，這樣的設定是全部的人都進到了`room_id: 1`的這個 stream，這樣不太對，我們會需要動態的去取得 room_id，你可以：
1. 從 url 裡抓
2. 寫在 html.erb 裡
```htmlmixed=
<div data-room-id="<%= @room.id %>">
    ...
</div>
```
這樣就可以找到對的連線，不過別忘了在js的部分加上，`'turbolinks:load'`的監聽事件：
```javascript=
document.addEventListener('turbolinks:load', function () {
    channel: "RoomChannel",
    room_id: $('#room_messages).attr('data-room-id')
  }, 
  ...
})
```
這樣就有辦法在不同的 room 裡面有不同的 stream 了！感謝各位看到這邊，若有任何建議，請各位不吝指教！我們明天見！
![](https://i.imgur.com/PPbpd2b.gif)