--- title: 12th 鐵人賽 Day_26 action cable ?(3) tags: 12th 鐵人賽 --- # 12th 鐵人賽 Day_26 action cable ?(3) 嗨!各位朋友大家好,烤肉節快樂,我是阿圓,一樣有請今天的one piece: ![](https://i.imgur.com/mzwoFQx.png) (烤肉慶典持續中!) 昨天我們說完了 Pub/Sub 模式,今天來說說 Rails 中的 action cable。 # action cable 基本介紹 再來複習一下昨天的圖: ![](https://miro.medium.com/max/450/1*-GHFC93E4ODwNc98IE5_vA.png) >publisher 發送出去的訊息,透過代理層(message broker)的方式將訊息廣播給 subscriber 而 Rails 中,代理層的部分是 channel,可以透過產生器,來產生channel `rails g channel xxx` xxx 可以換成想取的名字 ~~(例如,親親小可愛之類的)~~,會建立出下面這些檔案: ```bash= Running via Spring preloader in process 27571 invoke test_unit create test/channels/xxx_channel_test.rb create app/channels/xxx_channel.rb identical app/javascript/channels/index.js identical app/javascript/channels/consumer.js create app/javascript/channels/xxx_channel.js ``` 先來看 `app/channels/xxx_channel.rb`,這裡面是定義當 subscriber,訂閱,或是取消訂閱 channel時的事情。 ```ruby= class XxxChannel < ApplicationCable::Channel # 會有一個最上層的 channel,底下有很多的小 channel。 def subscribed stream_from "qqq_stream" end def unsubscribed # Any cleanup needed when channel is unsubscribed end end ``` channel 透過 stream 來廣播訊息,常用的有以下方法: `stop_all_streams()` :取消所有stream。 `stream_from "xxx_channel"` :透過名為xxx_channel的stream 來廣播。 `stream_for (model)` :可以透過以建立的 model,來產生stream 廣播。 --- 而`app/javascript/channels/xxx_channel.js`,則是定義了 client 端的行為,分別有: ```javascript= import consumer from "./consumer" consumer.subscriptions.create("XxxChannel", { 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) { // 接收資料 // Called when there's incoming data on the websocket for this channel } }); ``` 其中 `consumer.subscriptions.create("XxxChannel",{...})`,這裡的意思是將 consumer 連上 XxxChannel,當 channel 那邊透過 stream(上面定義的名稱是'qqq_stream') 廣播出訊息,就會藉由 received 的 function 接收到資料。 這樣已經將簡單的連線做好了,但若要實際看到效果,還需要做一點設置: ```yaml= # /cable.yml development: adapter: async #把這邊改成 redis test: adapter: test production: adapter: redis url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> channel_prefix: Test_production ``` (redis 是一種無關聯性、 key-value 型的資料庫,一般會搭配關聯性資料庫,作為快取用,其他詳細介紹,請參考 [wiki](https://en.wikipedia.org/wiki/Redis)) 最後就可以去 rails console 裡面: ```bash= ActionCable.server.broadcast "qqq_channel", {message:"Hello world!"} # 請記得,channel 是透過 stream 來廣播訊息! ``` 這樣身為`XxxChannel`中`qqq_stream`的訂閱者,都可以收到這條訊息,並且在瀏覽器的 console 裡顯示出來。 ![](https://i.imgur.com/2aTpxgg.png) (若廣播成功會回傳1) 以上就是今天的 action cable 基本介紹,明天我們再來進階一些,感謝各位看到這邊,若有任何建議,請各位不吝指教!我們明天見! ![](https://i.imgur.com/PPbpd2b.gif) --- #### 參考文章 [官方文件](https://guides.rubyonrails.org/action_cable_overview.html) [官方手冊](https://api.rubyonrails.org/classes/ActionCable/Channel/Streams.html)