35
34

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.

Action Cable でプログレスバーを更新する

Last updated at Posted at 2016-08-26

概要

こんにちは、QUANON です。

Rails 5 の Action Cable の登場により、Rails アプリケーションの可能性がぐっと広がりましたね。今回はその Action Cable のシンプルな利用例を 1 つご紹介したいと思います。

利用例

サーバ側で何か重い処理を実行しており、その進捗率を逐次ユーザに伝えることができれば便利ですよね。例えば「ユーザから大量データの CSV ファイルの生成リクエストを受け付けて、その生成状況を画面上のプログレスバーにリアルタイムで表示する」などです。クライアントから Ajax 通信でサーバに進捗率を定期的に問い合わせ、その結果を受けてプログレスバーを更新することも可能ですが、できればもっとスマートな方法を選びたいですね。

そこで Action Cable の出番です。WebSocket を使って、サーバからクライアントに直接進捗率を送ってみます。

なお、プログレスバーの HTML はこんな感じです。Bootstrap 4プログレスバーを使用しています。

<div class="progress-percentage text-xs-center">0%</div>
<progress class="progress progress-striped" max="100" value="0"></progress>

また Action Cable 自体についての説明やセットアップ方法については省略します。

最初に Channel クラスを作成します。まずサーバ側です。

app/channels/progresses_channel.rb
class ProgressesChannel < ApplicationCable::Channel
  def follow(data)
    stream_from("progresses:#{data['progress_id'].to_i}")
  end
end

次にクライアント側です。

app/assets/javascripts/channels/progresses.coffee
App.progresses = App.cable.subscriptions.create 'ProgressesChannel',
  connected: ->
    @install()
    @follow()

  received: (data) ->
    $('.progress-percentage').text("#{data.percent}%")
    $('progress').prop('value', data.percent)

  follow: ->
    # 例示のため、購読対象の識別子 (progress_id) は決め打ち
    @perform('follow', progress_id: 1)

  install: ->
    $(document).on('page:change', -> App.progresses.follow())

実装が終わったら Rails サーバを起動します。ここでは Action Cable サーバは Rails サーバに組み込まれていることを想定します (別のサーバとして起動することも可能なため) 。動作確認のため、別途 Rails コンソールも起動します。ここで注意点ですが、開発環境のデフォルトのサブスクリプションアダプタasync です。これでは同一のプロセスからの broadcast しか有効になりません。つまり Action Cable サーバと別プロセスである Rails コンソールから broadcast を実行しても何も起きません。そこで Redis を使うように設定しておきます。

config/cable.yml
development:
  adapter: redis
  url: redis://localhost:6379

では Rails コンソールから broadcast を実行してみます。今回の例では、

ActionCable.server.broadcast('progresses:1', percent: 64)

のようなコードを実行します。

progress.gif

Rails コンソールで実行したコードと画面のプログレスバーが同期しているのが分かります。

実際は ActiveJob を利用して、バックグラウンドジョブの中で broadcast を実行することになると思います。

感想

Action Cable は様々な場面で役立ちそうですし、なによりリアルタイムに動く様子は実装していて非常に楽しいです。Rails 5 は最高ですね :blush::two_hearts:
皆さんも是非 Action Cable をエンジョイしてみてください。

35
34
2

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
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?