鹿児島大学でアプリ開発サークルをやっている@gakutomoです。
今回はVue.jsを使ったWebアプリケーションにチャット機能を組み込みたかったのでRailsのActionCableを使って爆速実装してみました
ActionCableとは
WebSocketを扱うRails5の新機能
チャットのようなリアルタイムにデータ更新するアプリが作れる
こういうやつ
動作環境
クライアント側
- macOS High Sierra
- Google Chrome
- Vue.js
サーバ側
- CentOS 7
- Rails 5.2
サーバ側の実装手順
Railsアプリケーションは作成済みとします
チャンネルの作成
console
rails g channel message
チャンネルの設定
app/channels/message_channel.rb
class MessageChannel < ApplicationCable::Channel
# チャンネル接続時に呼ばれる
def subscribed
stream_from "message_channel"
end
# メッセージをブロードキャストするためのアクション
def speak(data)
ActionCable.server.broadcast 'message_channel', message: data['message']
end
end
ルーティングを追加
config/route.rb
Rails.application.routes.draw do
# 以下を追記
mount ActionCable.server => '/cable'
end
クライアント側の実装手順
Vue.jsで実装します。RailsのWebPackerはうまくいかなかったので、ローカルでWebPack使って開発してます。
まず必要なパッケージをインストールします。
console
npm install actioncable
main.jsをエントリーポイントとして進めていきます
main.js
import Vue from 'vue';
import ActionCable from 'actioncable';
import Chat from './chat.vue';
const cable = ActionCable.createConsumer('ws:hoge.com:3000/cable');
Vue.prototype.$cable = cable;
new Vue({
components: {
Chat,
template: '<Chat/>',
},
}).$mount('#app');
通信部分の実装
chat.vue
<template>
<div>
<input v-model="msgBox" placeholder="message here"></input>
<button v-if="messageChannel" @click="speak">送信</button>
</div>
</template>
<script>
export default {
data() {
return {
msgBox: "",
messages: [],
messageChannel: null,
};
},
created() {
this.messageChannel = this.$cable.subscriptions.create( "MessageChannel",{
received: (data) => {
this.messages.push(data)
},
})
},
methods: {
speak() {
this.messageChannel.perform('speak', {
message: msgBox,
});
},
},
}
</script>
ハマりどころ
- スマホからだと以下の設定をしないと接続できなかった
- httpsからのWebSocketはwss://にしないといけない
config/application.rb
ActionCable.server.config.disable_request_forgery_protection = true
config.action_cable.url = 'wss://hogehoge.com/cable'
参考
Rails 5 + ActionCableで作る!シンプルなチャットアプリ
railsとvueでリアルタイムな注文システムを作ってみた
ActionCable の README を読んでチャットアプリを作ってみた
フロントエンドで ActionCable を npm 経由で使う
Action Cable でプログレスバーを更新する