ホーム DoRuby ActionCable実装しようwith webpack
 

ActionCable実装しようwith webpack

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Action Cableをイケてる構成のrailsで使いこなそう

ActionCable 使ってますか?

Rails5以降から導入されたActionCable
公式ドキュメントではチャットの実装などで使われていますが、色々な使い方ができそうです
sidekiqに投げた処理の結果を非同期で受信するとか

執筆時点では世の中に知見が多くなかったので実装体験記を残します

導入

rails g channel hoge_channelでActionCable導入に必要なアレコレが生成されるよ
ただしcoffee scriptだしSprocketsのアセットパイプラインに乗る形でフロントのスクリプトが吐き出される
(Rails5.2の場合)

うちの案件はwebpack導入してるしcoffe scriptなんて書いた事無い
そんな場合は下記コマンドでライブラリを導入しましょう

yarn add actioncable
または
npm install actioncable

そしてベースとなるcable.jsはこんな感じに
自分はapp/javascripts/channelsディレクトリに設置しました

# app/javascripts/channels/cable.js

import cable from “actioncable”;

let consumer;

function createChannel(...args) {
  if (!consumer) {
    consumer = cable.createConsumer();
  }
  return consumer.subscriptions.create(...args);
}

export default createChannel;

各チャンネルのjsはこんな感じ

# app/javascripts/channels/test_channel.js
import createChannel from “./cable”;    //cable.jsのパスは適宜変更してください
$(function(){
  const channel = createChannel(“TestChannel”, {
    received(message) {
      alert(mesage); # この辺に受信時の処理を色々書く、今回は受信したものを取り敢えずブラウザにアラートとして表示する
    }
  });

  // rubyのactioncableで実装した処理を()呼ぶ
  function method_name(message) {
     channel.perform(“method_name”, { message });
  }
});

ruby側の実装は公式ドキュメントで紹介されている実装から特に変更点はないです

設定

よ~し取り敢えず検証用にデータを受信したらブラウザのアラートに出す機能作ったので動かしてみるか~
おや…動かん…エラーが出てるな

設定に不足がある場合はブラウザのデバッグコンソールに下記のようなエラーが表示されます

WebSocket handshake: unexpected response code: 502

または

WebSocket connection to 'wss://example.com' failed: WebSocket is 'test channel~js'
closed before the connection is estrablished.

色々な記事にdockerで動かしている場合は専用のコンテナ建てろみたいなことを書いていましたが検証の結果不要でした
自分の場合 config.reload_classes_only_on_change が false になっていました
windiwsで開発していた時に変更がホットリロードされなかったのでここの設定弄ったのですがaction_cableの挙動にかかわるようです

その他設定

config/cable.yml でdevelop環境もredisを使用する

development:
  adapter: redis
  url: redis://10.10.3.153:6381 => 方法は自由ですがsidekiqやセッション情報とは異なるURLになるように工夫しましょう
  channel_prefix: appname_development

test:
  adapter: async

production:
  adapter: redis
  url: redis://10.10.3.153:6381
  channel_prefix: appname_production
config/environment/production.rbで自分ドメインからのリクエストを許可する

config.action_cable.allowed_request_origins = ['https://rubyonrails.com', %r{http://ruby.*}]
config/application.rb でrailsアプリケーション上にマウントするパスを指定する

class Application < Rails::Application
  config.action_cable.mount_path = '/websocket'
end 

config/routes.rbにマウントするパスを指定する方法を紹介する記事も見かけましたがたぶんこっちの方が良いと思います
viewファイルのヘッダーに<%= csrf_meta_tags %>を記載する

その他開発環境の設定や本番サーバーの構成によって何かしらの設定が必要になる場合があります
nginxのconfigファイルにリクエストヘッダーの設定書くとか…

うまくAction Cableが動けばRailsコンソール立ち上げて用意したchannelクラスのメソッドを呼んでみるなりなんなりすれば動くはずです
パターンが膨大すぎて個別の症状に応じて苦戦するのはなんだかインフラエンジニアっぽい感じでした
つまりググっても出てこないエラーとの戦いが結構大変だった

記事を共有
モバイルバージョンを終了