35
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails(ActionCable)とNuxt.jsでチャットアプリを作ってみる

Last updated at Posted at 2019-01-05

シェアフル AdventCalendar2018 16 日目の記事です。

はじめに

つい最近RubyとVue.jsについて勉強し始めた身なのですが、勉強がてらチャットアプリを作ってみました。
Rails5にはActionCableというWebsocket通信を標準でサポートしてくれるものがあるようなので、今回はこちらとNuxt.jsを用いて双方向通信を行いました。

完成品としては、以下のようなものになります。
作成するチャットアプリイメージ

ActionCableとは

ActionCableは、RailsにおいてWebsocketによる双方向通信をシームレスに行うことを可能にする技術であり、Rails5から組み込まれました。
Websocketというのは、HTTP上で双方向通信を可能にするプロトコルのことで、これを用いることでチャットアプリ等のリアルタイムなアプリケーション開発を行うことができます。

構成

  • サーバサイド

Ruby 2.6.0
Rails 5.2.2

  • フロントエンド

Nuxt.js 2.0.0
Node 8.11.0
npm 5.6.0

サーバサイドの実装

今回、サーバサイドはまずは、RailsをAPIモードで作成します。

$ rails new websocket-test --api
$ bundle install --path vendor/bundle

DBはこの記事のチャットでは扱わないため、DB設定は済んでいる前提で進めていきます。

$ rails g channel post

これで、追加された下記ファイルを変更していきます。

app/channels/post_channel.rb
class PostChannel < ApplicationCable::Channel
  def subscribed
    # stream_from "some_channel"
    stream_from 'post:message'
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def post(data)
    PostChannel.broadcast_to('message', data['message'])
  end
end

上記を作成した段階で、一度websocketとの疎通が通るかの確認を行ってみます。

フロント側を作成するサーバ上で wscat というものを用いて疎通確認を行います。
wscatは、Node.js上でwebsocketを扱う際に使う ws というモジュールに同梱されており、コマンドライン上でwebsocketサーバへの接続を行ったり、websocketサーバを立てたりすることができます。

$ npm i -g ws

インストールが終われば、rails上で rails s を行い、 railsのサーバ上に対して接続してみます。

$ wscat -c ws://<railsサーバのIP>:<railsを起動しているポート>/cable

接続がうまくいけば、以下のようになり、pingが数秒おきに返ってきます。

connected (press CTRL+C to quit)
< {"type":"welcome"}
< {"type":"ping","message":154653xxxx}
< {"type":"ping","message":154653xxxx}

この際、Vagrantなどでrailsサーバを立てていると、 Request origin not allowed といったエラーが返ってきますので、下記を追記します。

config/initializers/action_cable.rb
ActionCable.server.config.disable_request_forgery_protection = true

フロントエンドの実装

こちらはNuxt.jsで作成したのですが、最初に create-nuxt-app を使った以外はnuxtに関係あるものは使っていないので、だいたいVueです。
cssフレームワークとしては、Buefyを利用しています。

画面に関しては最後にソースをあげていますのでそちらをご確認ください。
記事内では、websocketに関連する部分のみをpickして説明していきます。

まずは、フロントからActionCableへの接続を行うために必要なライブラリをインストールします。

$ npm i actioncable --save

画面側は省き、script部分のみ説明していきます。
まずは、全体です。

<script>
import ActionCable from 'actioncable';

export default {
  data() {
    return {
      messageText: ""
    };
  },
  created() {
    const cable = ActionCable.createConsumer('ws://<railsサーバIP>:<起動port>/cable');

    this.messageChannel = cable.subscriptions.create( "PostChannel",{
      received: (data) => {
        this.$store.commit("addMessage", data);
      },
    })
  },
  methods: {
    handleClick: function() {
      //ActionCable PostChannelにおけるpostメソッドを実行する
      this.messageChannel.perform('post', { 
        message: this.messageText, 
      });
      // console.log(this.$store.state.messages);
      //メッセージ追加後にテキストボックスを空にする
      this.messageText = ""
    }
  }
};
</script>

まずは、created()内でwebsocketのサーバを指定し、先ほどRailsで作成したPostChannelに対してのsubscriptionを作成します。
コールバックとして、 connected , disconnected , received を作成すると、それぞれチャンネルへの接続時、接続の解除時、データ受信時に実行されます。

今回はreceivedのみを作成し、届いたメッセージをstoreに追加しています。
メッセージの画面出力としては、このようにしてstoreに追加された文字列の配列をfor文で出しているだけです。

  created() {
    const cable = ActionCable.createConsumer('ws://<railsサーバIP>:<起動port>/cable');

    this.messageChannel = cable.subscriptions.create( "PostChannel",{
      received: (data) => {
        this.$store.commit("addMessage", data);
      },
    })
  },

次に、テキストボックスからメッセージを入力し、送信ボタンを押した際のメソッドを見てみます。
createdで作成したthis.messageChannelを用いて、PostChannelにおけるpostメソッドの実行を行なっています。

  methods: {
    handleClick: function() {
      //ActionCable PostChannelにおけるpostメソッドを実行する
      this.messageChannel.perform('post', { 
        message: this.messageText, 
      });
      //メッセージ追加後にテキストボックスを空にする
      this.messageText = ""
    }
  }

このようにすることで、RailsのActionCableで作成したChannelに対して接続することができ、Nuxt.js上から双方向通信ができるようになります。

終わりに

Vue.jsもRailsもほぼほぼ素人だったのですが、ActionCableのおかげでチャットアプリを簡単に作成することができました。
今回はNuxt自体の便利さはほとんど活かせていないので、これを発展させて何かアプリを作れたらなと思います。

今回、nuxt.jsとRailsは別サーバ上で作成したため、 initializers の設定が必要になりました。参考サイトにも記載があったのですが、実際には同じサーバ上におき、nginxなどで制御する方が良さそうです。
今回のソースは以下に置いているので、よかったら参考にしてください。

今回のソース

参考

Rails5のAction Cableの試食
Vagrantでサーバー立ててActionCableを試してる時にRequest origin not allowedがでて辛い

今回、上記の情報を参考にさせていただきました。誠にありがとうございました。

追記(2019/2/17)

コメントいただきrails側のソースも追記しました。記事の作業しかしてないので、ご参考程度でお願い致します。誤り等ありましたらお伝えください。
ソース

35
32
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?